commit e9acdcbee2778c99e094266b9c7f4df705f09992 Author: algorithmx2 Date: Fri Dec 27 16:59:59 2013 -0600 AE2 First Commit, the dawn of 1.7 hast arrived. diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..c10049b5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "api"] + path = api + url = https://github.com/AlgorithmX2/Applied-Energistics-2-API.git diff --git a/api b/api new file mode 160000 index 00000000..1aa68044 --- /dev/null +++ b/api @@ -0,0 +1 @@ +Subproject commit 1aa680440944ff48b144201545f62db08ed28261 diff --git a/block/AEBaseBlock.java b/block/AEBaseBlock.java new file mode 100644 index 00000000..0a59ce8b --- /dev/null +++ b/block/AEBaseBlock.java @@ -0,0 +1,688 @@ +package appeng.block; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.resources.Resource; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Icon; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec3; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IMemoryCard; +import appeng.api.implementations.MemoryCardMessages; +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.BlockRenderInfo; +import appeng.client.render.WorldRender; +import appeng.client.texture.FlipableIcon; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; +import appeng.helpers.ICustomCollision; +import appeng.tile.AEBaseTile; +import appeng.tile.networking.TileCableBus; +import appeng.util.LookDirection; +import appeng.util.Platform; +import appeng.util.SettingsFrom; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class AEBaseBlock extends BlockContainer implements IAEFeature +{ + + private String FeatureFullname; + private String FeatureSubname; + private AEFeatureHandler feature; + + private Class tileEntityType = null; + protected boolean isOpaque = true; + protected boolean isFullSize = true; + + @SideOnly(Side.CLIENT) + public Icon renderIcon; + + @SideOnly(Side.CLIENT) + BlockRenderInfo renderInfo; + + @Override + public String toString() + { + return FeatureFullname; + } + + @SideOnly(Side.CLIENT) + protected Class getRenderer() + { + return BaseBlockRender.class; + } + + @Override + @SideOnly(Side.CLIENT) + public int getRenderType() + { + return WorldRender.instance.getRenderId(); + } + + @SideOnly(Side.CLIENT) + private FlipableIcon optionaIcon(IconRegister ir, String Name, Icon substitute) + { + // if the input is an flippable icon find the original. + while (substitute instanceof FlipableIcon) + substitute = ((FlipableIcon) substitute).getOriginal(); + + if ( substitute != null ) + { + try + { + ResourceLocation resLoc = new ResourceLocation( Name ); + resLoc = new ResourceLocation( resLoc.getResourceDomain(), String.format( "%s/%s%s", new Object[] { "textures/blocks", + resLoc.getResourcePath(), ".png" } ) ); + + Resource res = Minecraft.getMinecraft().getResourceManager().getResource( resLoc ); + if ( res != null ) + return new FlipableIcon( ir.registerIcon( Name ) ); + } + catch (Throwable e) + { + return new FlipableIcon( substitute ); + } + } + + return new FlipableIcon( ir.registerIcon( Name ) ); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister iconRegistry) + { + BlockRenderInfo info = getRendererInstance(); + FlipableIcon topIcon; + FlipableIcon bottomIcon; + FlipableIcon sideIcon; + FlipableIcon eastIcon; + FlipableIcon westIcon; + FlipableIcon southIcon; + FlipableIcon northIcon; + + this.blockIcon = topIcon = optionaIcon( iconRegistry, this.getTextureName(), null ); + bottomIcon = optionaIcon( iconRegistry, this.getTextureName() + "Bottom", topIcon ); + sideIcon = optionaIcon( iconRegistry, this.getTextureName() + "Side", topIcon ); + eastIcon = optionaIcon( iconRegistry, this.getTextureName() + "East", sideIcon ); + westIcon = optionaIcon( iconRegistry, this.getTextureName() + "West", sideIcon ); + southIcon = optionaIcon( iconRegistry, this.getTextureName() + "Front", sideIcon ); + northIcon = optionaIcon( iconRegistry, this.getTextureName() + "Back", sideIcon ); + + info.updateIcons( bottomIcon, topIcon, northIcon, southIcon, eastIcon, westIcon ); + } + + @Override + @SideOnly(Side.CLIENT) + public Icon getIcon(int direction, int metadata) + { + if ( renderIcon != null ) + return renderIcon; + + return getRendererInstance().getTexture( ForgeDirection.getOrientation( direction ) ); + } + + @Override + public Icon getBlockTexture(IBlockAccess w, int x, int y, int z, int s) + { + return getIcon( mapRotation( w, x, y, z, s ), 0 ); + } + + protected void setTileEntiy(Class c) + { + GameRegistry.registerTileEntity( tileEntityType = c, FeatureFullname ); + } + + protected void setfeature(EnumSet f) + { + feature = new AEFeatureHandler( f, this, FeatureSubname ); + } + + protected AEBaseBlock(Class c, Material mat) { + this( c, mat, null ); + setLightOpacity( 15 ); + setLightValue( 0 ); + setHardness( 1.2F ); + } + + protected AEBaseBlock(Class c, Material mat, String subname) { + super( Configuration.instance.getBlockID( c, subname ), mat ); + + if ( mat == Material.glass ) + setStepSound( Block.soundGlassFootstep ); + else if ( mat == Material.rock ) + setStepSound( Block.soundStoneFootstep ); + else + setStepSound( Block.soundMetalFootstep ); + + FeatureFullname = AEFeatureHandler.getName( c, subname ); + FeatureSubname = subname; + } + + @Override + final public AEFeatureHandler feature() + { + return feature; + } + + public boolean isOpaque() + { + return isOpaque; + } + + @Override + final public boolean isOpaqueCube() + { + return isOpaque; + } + + @Override + public boolean renderAsNormalBlock() + { + return isFullSize && isOpaque; + } + + @Override + final public boolean isBlockNormalCube(World world, int x, int y, int z) + { + return isFullSize; + } + + public boolean hasBlockTileEntity() + { + return tileEntityType != null; + } + + @Override + final public boolean hasTileEntity(int metadata) + { + return hasBlockTileEntity(); + } + + public Class getTileEntityClass() + { + return tileEntityType; + } + + @SideOnly(Side.CLIENT) + public BlockRenderInfo getRendererInstance() + { + if ( renderInfo != null ) + return renderInfo; + + try + { + return renderInfo = new BlockRenderInfo( getRenderer().newInstance() ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + @Override + final public TileEntity createTileEntity(World world, int metadata) + { + try + { + return tileEntityType.newInstance(); + } + catch (Throwable e) + { + throw new RuntimeException( e ); + } + } + + @Override + final public TileEntity createNewTileEntity(World world) + { + return createTileEntity( world, 0 ); + } + + final public T getTileEntity(IBlockAccess w, int x, int y, int z) + { + if ( !hasBlockTileEntity() ) + return null; + + TileEntity te = w.getBlockTileEntity( x, y, z ); + if ( tileEntityType.isInstance( te ) ) + return (T) te; + + return null; + } + + @Override + final public boolean rotateBlock(World w, int x, int y, int z, ForgeDirection axis) + { + IOrientable rotateable = null; + + if ( hasBlockTileEntity() ) + { + rotateable = (AEBaseTile) getTileEntity( w, x, y, z ); + } + else if ( this instanceof IOrientableBlock ) + { + rotateable = ((IOrientableBlock) this).getOrientable( w, x, y, z ); + } + + if ( rotateable != null && rotateable.canBeRotated() ) + { + ForgeDirection forward = rotateable.getForward(); + ForgeDirection up = rotateable.getUp(); + + for (int rs = 0; rs < 4; rs++) + { + forward = Platform.rotateAround( forward, axis ); + up = Platform.rotateAround( up, axis ); + + if ( this.isValidOrientation( w, x, y, z, forward, up ) ) + { + rotateable.setOrientation( forward, up ); + return true; + } + } + } + + return false; + } + + public ForgeDirection mapRotation(IOrientable ori, ForgeDirection dir) + { + // case DOWN: return bottomIcon; + // case UP: return blockIcon; + // case NORTH: return northIcon; + // case SOUTH: return southIcon; + // case WEST: return sideIcon; + // case EAST: return sideIcon; + + ForgeDirection forward = ori.getForward(); + ForgeDirection up = ori.getUp(); + ForgeDirection west = ForgeDirection.UNKNOWN; + + if ( forward == null || up == null ) + return dir; + + int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + for (ForgeDirection dx : ForgeDirection.VALID_DIRECTIONS) + if ( dx.offsetX == west_x && dx.offsetY == west_y && dx.offsetZ == west_z ) + west = dx; + + if ( dir.equals( forward ) ) + return ForgeDirection.SOUTH; + if ( dir.equals( forward.getOpposite() ) ) + return ForgeDirection.NORTH; + + if ( dir.equals( up ) ) + return ForgeDirection.UP; + if ( dir.equals( up.getOpposite() ) ) + return ForgeDirection.DOWN; + + if ( dir.equals( west ) ) + return ForgeDirection.WEST; + if ( dir.equals( west.getOpposite() ) ) + return ForgeDirection.EAST; + + return ForgeDirection.UNKNOWN; + } + + int mapRotation(IBlockAccess w, int x, int y, int z, int s) + { + IOrientable ori = null; + + if ( hasBlockTileEntity() ) + { + ori = (AEBaseTile) getTileEntity( w, x, y, z ); + } + else if ( this instanceof IOrientableBlock ) + { + ori = ((IOrientableBlock) this).getOrientable( w, x, y, z ); + } + + if ( ori != null && ori.canBeRotated() ) + { + return mapRotation( ori, ForgeDirection.getOrientation( s ) ).ordinal(); + } + + return s; + } + + @Override + final public ForgeDirection[] getValidRotations(World w, int x, int y, int z) + { + if ( hasBlockTileEntity() ) + { + AEBaseTile obj = getTileEntity( w, x, y, z ); + if ( obj != null && obj.canBeRotated() ) + { + return ForgeDirection.VALID_DIRECTIONS; + } + } + + return new ForgeDirection[0]; + } + + @Override + public void breakBlock(World w, int x, int y, int z, int a, int b) + { + AEBaseTile te = getTileEntity( w, x, y, z ); + if ( te != null ) + { + if ( te.dropItems ) + { + ArrayList drops = new ArrayList(); + te.getDrops( w, x, y, z, drops ); + + // Cry ;_; ... + Platform.spawnDrops( w, x, y, z, drops ); + } + } + + super.breakBlock( w, x, y, z, a, b ); + if ( te != null ) + w.setBlockTileEntity( x, y, z, null ); + } + + @Override + public MovingObjectPosition collisionRayTrace(World w, int x, int y, int z, Vec3 a, Vec3 b) + { + ICustomCollision collisionHandler = null; + + if ( this instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) this; + else + { + AEBaseTile te = getTileEntity( w, x, y, z ); + if ( te instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) te; + } + + if ( collisionHandler != null ) + { + Iterable bbs = collisionHandler.getSelectedBoundingBoxsFromPool( w, x, y, z ); + MovingObjectPosition br = null; + + double lastDist = 0; + + for (AxisAlignedBB bb : bbs) + { + setBlockBounds( (float) bb.minX, (float) bb.minY, (float) bb.minZ, (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ ); + + MovingObjectPosition r = super.collisionRayTrace( w, x, y, z, a, b ); + + setBlockBounds( 0, 0, 0, 1, 1, 1 ); + + if ( r != null ) + { + double xLen = (a.xCoord - r.hitVec.xCoord); + double yLen = (a.yCoord - r.hitVec.yCoord); + double zLen = (a.zCoord - r.hitVec.zCoord); + + double thisDist = xLen * xLen + yLen * yLen + zLen * zLen; + if ( br == null || lastDist > thisDist ) + { + lastDist = thisDist; + br = r; + } + } + } + + if ( br != null ) + { + return br; + } + return null; + } + + setBlockBounds( 0, 0, 0, 1, 1, 1 ); + return super.collisionRayTrace( w, x, y, z, a, b ); + } + + @Override + final public AxisAlignedBB getSelectedBoundingBoxFromPool(World w, int x, int y, int z) + { + ICustomCollision collisionHandler = null; + AxisAlignedBB b = null; + + if ( this instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) this; + else + { + AEBaseTile te = getTileEntity( w, x, y, z ); + if ( te instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) te; + } + + if ( collisionHandler != null ) + { + if ( Platform.isClient() ) + { + LookDirection ld = Platform.getPlayerRay( Minecraft.getMinecraft().thePlayer ); + + Iterable bbs = collisionHandler.getSelectedBoundingBoxsFromPool( w, x, y, z ); + AxisAlignedBB br = null; + + double lastDist = 0; + + for (AxisAlignedBB bb : bbs) + { + setBlockBounds( (float) bb.minX, (float) bb.minY, (float) bb.minZ, (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ ); + + MovingObjectPosition r = super.collisionRayTrace( w, x, y, z, ld.a, ld.b ); + + setBlockBounds( 0, 0, 0, 1, 1, 1 ); + + if ( r != null ) + { + double xLen = (ld.a.xCoord - r.hitVec.xCoord); + double yLen = (ld.a.yCoord - r.hitVec.yCoord); + double zLen = (ld.a.zCoord - r.hitVec.zCoord); + + double thisDist = xLen * xLen + yLen * yLen + zLen * zLen; + if ( br == null || lastDist > thisDist ) + { + lastDist = thisDist; + br = bb; + } + } + } + + if ( br != null ) + { + br.setBounds( br.minX + x, br.minY + y, br.minZ + z, br.maxX + x, br.maxY + y, br.maxZ + z ); + return br; + } + } + + for (AxisAlignedBB bx : collisionHandler.getSelectedBoundingBoxsFromPool( w, x, y, z )) + { + if ( b == null ) + b = bx; + else + { + double minX = Math.min( b.minX, bx.minX ); + double minY = Math.min( b.minY, bx.minY ); + double minZ = Math.min( b.minZ, bx.minZ ); + double maxX = Math.max( b.maxX, bx.maxX ); + double maxY = Math.max( b.maxY, bx.maxY ); + double maxZ = Math.max( b.maxZ, bx.maxZ ); + b.setBounds( minX, minY, minZ, maxX, maxY, maxZ ); + } + } + + b.setBounds( b.minX + x, b.minY + y, b.minZ + z, b.maxX + x, b.maxY + y, b.maxZ + z ); + } + else + b = super.getSelectedBoundingBoxFromPool( w, x, y, z ); + + return b; + } + + @Override + final public void addCollisionBoxesToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + ICustomCollision collisionHandler = null; + + if ( this instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) this; + else + { + AEBaseTile te = getTileEntity( w, x, y, z ); + if ( te instanceof ICustomCollision ) + collisionHandler = (ICustomCollision) te; + } + + if ( collisionHandler != null && bb != null ) + { + List tmp = new ArrayList(); + collisionHandler.addCollidingBlockToList( w, x, y, z, bb, tmp, e ); + for (AxisAlignedBB b : tmp) + { + b.minX += x; + b.minY += y; + b.minZ += z; + b.maxX += x; + b.maxY += y; + b.maxZ += z; + if ( bb.intersectsWith( b ) ) + out.add( b ); + } + } + else + super.addCollisionBoxesToList( w, x, y, z, bb, out, e ); + } + + @Override + public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) + { + super.onBlockDestroyedByPlayer( par1World, par2, par3, par4, par5 ); + } + + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + return false; + } + + @Override + final public boolean onBlockActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player != null ) + { + ItemStack is = player.inventory.getCurrentItem(); + if ( is != null ) + { + if ( Platform.isWrench( player, is, x, y, z ) && player.isSneaking() ) + { + int id = w.getBlockId( x, y, z ); + if ( id != 0 ) + { + AEBaseTile tile = getTileEntity( w, x, y, z ); + ItemStack[] drops = Platform.getBlockDrops( w, x, y, z ); + + if ( tile == null ) + return false; + + if ( tile instanceof TileCableBus ) + return false; + + ItemStack op = new ItemStack( this ); + for (ItemStack ol : drops) + { + if ( Platform.isSameItemType( ol, op ) ) + { + NBTTagCompound tag = tile.downloadSettings( SettingsFrom.DISMANTLE_ITEM ); + if ( tag != null ) + ol.setTagCompound( tag ); + } + } + + if ( Block.blocksList[id].removeBlockByPlayer( w, player, x, y, z ) ) + { + List l = new ArrayList(); + for (ItemStack iss : drops) + l.add( iss ); + Platform.spawnDrops( w, x, y, z, l ); + w.setBlockToAir( x, y, z ); + } + } + return false; + } + + if ( is.getItem() instanceof IMemoryCard ) + { + IMemoryCard memc = (IMemoryCard) is.getItem(); + if ( player.isSneaking() ) + { + AEBaseTile t = getTileEntity( w, x, y, z ); + if ( t != null ) + { + String name = getUnlocalizedName(); + NBTTagCompound data = t.downloadSettings( SettingsFrom.MEMORY_CARD ); + if ( data != null ) + { + memc.setMemoryCardContents( is, name, data ); + memc.notifyUser( this, player, MemoryCardMessages.SETTINGS_SAVED ); + return false; + } + } + } + else + { + String name = memc.getSettingsName( is ); + NBTTagCompound data = memc.getData( is ); + if ( getUnlocalizedName().equals( name ) ) + { + AEBaseTile t = getTileEntity( w, x, y, z ); + t.uploadSettings( SettingsFrom.MEMORY_CARD, data ); + memc.notifyUser( this, player, MemoryCardMessages.SETTINGS_LOADED ); + } + else + memc.notifyUser( this, player, MemoryCardMessages.INVALID_MACHINE ); + return false; + } + } + } + } + + return onActivated( w, x, y, z, player, side, hitX, hitY, hitZ ); + } + + public boolean isValidOrientation(World w, int x, int y, int z, ForgeDirection forward, ForgeDirection up) + { + return true; + } + + public void addInformation(ItemStack is, EntityPlayer player, List lines, boolean advancedItemTooltips) + { + + } + + public Class getItemBlockClass() + { + return AEBaseItemBlock.class; + } + +} diff --git a/block/AEBaseItemBlock.java b/block/AEBaseItemBlock.java new file mode 100644 index 00000000..638d9aaa --- /dev/null +++ b/block/AEBaseItemBlock.java @@ -0,0 +1,131 @@ +package appeng.block; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.client.render.ItemRenderer; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; + +public class AEBaseItemBlock extends ItemBlock +{ + + final AEBaseBlock blockType; + + public AEBaseItemBlock(int id) { + super( id ); + blockType = (AEBaseBlock) Block.blocksList[id + 256]; + if ( Platform.isClient() ) + MinecraftForgeClient.registerItemRenderer( blockType.blockID, ItemRenderer.instance ); + } + + @Override + public void addInformation(ItemStack is, EntityPlayer player, List lines, boolean advancedItemTooltips) + { + Block blk = Block.blocksList[getBlockID()]; + if ( blk instanceof AEBaseBlock ) + ((AEBaseBlock) blk).addInformation( is, player, lines, advancedItemTooltips ); + } + + @Override + public boolean placeBlockAt(ItemStack stack, EntityPlayer player, World w, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metadata) + { + ForgeDirection up = ForgeDirection.UNKNOWN; + ForgeDirection forward = ForgeDirection.UNKNOWN; + + IOrientable ori = null; + + if ( blockType.hasBlockTileEntity() ) + { + up = ForgeDirection.UP; + + byte rotation = (byte) (MathHelper.floor_double( (double) ((player.rotationYaw * 4F) / 360F) + 2.5D ) & 3); + + switch (rotation) + { + default: + case 0: + forward = ForgeDirection.SOUTH; + break; + case 1: + forward = ForgeDirection.WEST; + break; + case 2: + forward = ForgeDirection.NORTH; + break; + case 3: + forward = ForgeDirection.EAST; + break; + } + + if ( player.rotationPitch > 65 ) + { + up = forward.getOpposite(); + forward = ForgeDirection.UP; + } + else if ( player.rotationPitch < -65 ) + { + up = forward.getOpposite(); + forward = ForgeDirection.DOWN; + } + } + + if ( blockType instanceof IOrientableBlock ) + { + ori = ((IOrientableBlock) blockType).getOrientable( w, x, y, z ); + up = ForgeDirection.getOrientation( side ); + forward = ForgeDirection.SOUTH; + if ( up.offsetY == 0 ) + forward = ForgeDirection.UP; + + ori.setOrientation( forward, up ); + } + + if ( !blockType.isValidOrientation( w, x, y, z, forward, up ) ) + return false; + + if ( super.placeBlockAt( stack, player, w, x, y, z, side, hitX, hitY, hitZ, metadata ) ) + { + if ( blockType.hasBlockTileEntity() ) + { + AEBaseTile tile = blockType.getTileEntity( w, x, y, z ); + ori = tile; + + if ( tile == null ) + return true; + + if ( ori.canBeRotated() ) + { + if ( ori.getForward() == null || ori.getUp() == null || // null + tile.getForward() == ForgeDirection.UNKNOWN || ori.getUp() == ForgeDirection.UNKNOWN ) + ori.setOrientation( forward, up ); + } + + tile.onPlacement( stack, player, side ); + } + else if ( blockType instanceof IOrientableBlock ) + { + ori.setOrientation( forward, up ); + } + + return true; + } + return false; + } + + @Override + public boolean isBookEnchantable(ItemStack itemstack1, ItemStack itemstack2) + { + return false; + } + +} diff --git a/block/AEBaseItemBlockChargeable.java b/block/AEBaseItemBlockChargeable.java new file mode 100644 index 00000000..876d1222 --- /dev/null +++ b/block/AEBaseItemBlockChargeable.java @@ -0,0 +1,118 @@ +package appeng.block; + +import java.text.MessageFormat; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.PowerUnits; +import appeng.api.implementations.IAEItemPowerStorage; +import appeng.util.Platform; + +public class AEBaseItemBlockChargeable extends AEBaseItemBlock implements IAEItemPowerStorage +{ + + public AEBaseItemBlockChargeable(int id) { + super( id ); + } + + @Override + public void addInformation(ItemStack is, EntityPlayer player, List lines, boolean advancedItemTooltips) + { + NBTTagCompound tag = is.getTagCompound(); + double internalCurrentPower = 0; + double internalMaxPower = getMax( is ); + + if ( tag != null ) + { + internalCurrentPower = tag.getDouble( "internalCurrentPower" ); + } + + double percent = internalCurrentPower / internalMaxPower; + + lines.add( Platform.gui_localize( "Stored Energy" ) + ":" + MessageFormat.format( " {0,number,#} ", internalCurrentPower ) + + Platform.gui_localize( PowerUnits.AE.unlocalizedName ) + " - " + + MessageFormat.format( " {0,number,#.##%} ", percent ) ); + + } + + private double getMax(ItemStack is) + { + Block blk = Block.blocksList[getBlockID()]; + if ( blk == AEApi.instance().blocks().blockEnergyCell.block() ) + return 200000; + else + return 8 * 200000; + } + + private double getInternal(ItemStack is) + { + NBTTagCompound nbt = Platform.openNbtData( is ); + return nbt.getDouble( "internalCurrentPower" ); + } + + private void setInternal(ItemStack is, double amt) + { + NBTTagCompound nbt = Platform.openNbtData( is ); + nbt.setDouble( "internalCurrentPower", amt ); + } + + @Override + public double injectAEPower(ItemStack is, double amt) + { + double internalCurrentPower = getInternal( is ); + double internalMaxPower = getMax( is ); + internalCurrentPower += amt; + if ( internalCurrentPower > internalMaxPower ) + { + amt = internalCurrentPower - internalMaxPower; + internalCurrentPower = internalMaxPower; + setInternal( is, internalCurrentPower ); + return amt; + } + + setInternal( is, internalCurrentPower ); + return 0; + } + + @Override + public double extractAEPower(ItemStack is, double amt) + { + double internalCurrentPower = getInternal( is ); + if ( internalCurrentPower > amt ) + { + internalCurrentPower -= amt; + setInternal( is, internalCurrentPower ); + return amt; + } + + amt = internalCurrentPower; + setInternal( is, 0 ); + return amt; + } + + @Override + public double getAEMaxPower(ItemStack is) + { + double internalMaxPower = getMax( is ); + return internalMaxPower; + } + + @Override + public double getAECurrentPower(ItemStack is) + { + double internalCurrentPower = getInternal( is ); + return internalCurrentPower; + } + + @Override + public AccessRestriction getPowerFlow(ItemStack is) + { + return AccessRestriction.WRITE; + } + +} diff --git a/block/grindstone/BlockCrank.java b/block/grindstone/BlockCrank.java new file mode 100644 index 00000000..8f3790e8 --- /dev/null +++ b/block/grindstone/BlockCrank.java @@ -0,0 +1,114 @@ +package appeng.block.grindstone; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.ICrankable; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderBlockCrank; +import appeng.core.features.AEFeature; +import appeng.tile.AEBaseTile; +import appeng.tile.grindstone.TileCrank; + +public class BlockCrank extends AEBaseBlock +{ + + public BlockCrank() { + super( BlockCrank.class, Material.wood ); + setfeature( EnumSet.of( AEFeature.GrindStone ) ); + setTileEntiy( TileCrank.class ); + setLightOpacity( 0 ); + isFullSize = isOpaque = false; + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer p, int side, float hitX, float hitY, float hitZ) + { + AEBaseTile tile = getTileEntity( w, x, y, z ); + if ( tile instanceof TileCrank ) + { + ((TileCrank) tile).power(); + } + return true; + } + + @Override + public Class getRenderer() + { + return RenderBlockCrank.class; + } + + private boolean isCrankable(World w, int x, int y, int z, ForgeDirection offset) + { + TileEntity te = w.getBlockTileEntity( x + offset.offsetX, y + offset.offsetY, z + offset.offsetZ ); + if ( te instanceof ICrankable ) + { + return ((ICrankable) te).canCrankAttach( offset.getOpposite() ); + } + return false; + } + + private ForgeDirection findCrankable(World w, int x, int y, int z) + { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + if ( isCrankable( w, x, y, z, dir ) ) + return dir; + return ForgeDirection.UNKNOWN; + } + + @Override + public boolean canPlaceBlockAt(World w, int x, int y, int z) + { + return findCrankable( w, x, y, z ) != ForgeDirection.UNKNOWN; + } + + @Override + public boolean isValidOrientation(World w, int x, int y, int z, ForgeDirection forward, ForgeDirection up) + { + TileEntity te = w.getBlockTileEntity( x, y, z ); + return !(te instanceof TileCrank) || isCrankable( w, x, y, z, up.getOpposite() ); + } + + private void dropCrank(World w, int x, int y, int z) + { + w.destroyBlock( x, y, z, true ); + w.markBlockForUpdate( x, y, z ); + } + + @Override + public void onBlockPlacedBy(World w, int x, int y, int z, EntityLivingBase p, ItemStack is) + { + AEBaseTile tile = getTileEntity( w, x, y, z ); + if ( tile != null ) + { + ForgeDirection mnt = findCrankable( w, x, y, z ); + ForgeDirection forward = ForgeDirection.UP; + if ( mnt == ForgeDirection.UP || mnt == ForgeDirection.DOWN ) + forward = ForgeDirection.SOUTH; + tile.setOrientation( forward, mnt.getOpposite() ); + } + else + dropCrank( w, x, y, z ); + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int id) + { + AEBaseTile tile = getTileEntity( w, x, y, z ); + if ( tile != null ) + { + if ( !isCrankable( w, x, y, z, tile.getUp().getOpposite() ) ) + dropCrank( w, x, y, z ); + } + else + dropCrank( w, x, y, z ); + } + +} diff --git a/block/grindstone/BlockGrinder.java b/block/grindstone/BlockGrinder.java new file mode 100644 index 00000000..2bea3bd7 --- /dev/null +++ b/block/grindstone/BlockGrinder.java @@ -0,0 +1,36 @@ +package appeng.block.grindstone; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.core.sync.GuiBridge; +import appeng.tile.grindstone.TileGrinder; +import appeng.util.Platform; + +public class BlockGrinder extends AEBaseBlock +{ + + public BlockGrinder() { + super( BlockGrinder.class, Material.rock ); + setfeature( EnumSet.of( AEFeature.GrindStone ) ); + setTileEntiy( TileGrinder.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer p, int side, float hitX, float hitY, float hitZ) + { + TileGrinder tg = getTileEntity( w, x, y, z ); + if ( tg != null && !p.isSneaking() ) + { + Platform.openGUI( p, tg, ForgeDirection.getOrientation(side),GuiBridge.GUI_GRINDER ); + return true; + } + return false; + } + +} diff --git a/block/mac/BlockContainmentWall.java b/block/mac/BlockContainmentWall.java new file mode 100644 index 00000000..ea906359 --- /dev/null +++ b/block/mac/BlockContainmentWall.java @@ -0,0 +1,19 @@ +package appeng.block.mac; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.mac.TileMolecularAssembler; + +public class BlockContainmentWall extends AEBaseBlock +{ + + public BlockContainmentWall() { + super( BlockContainmentWall.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.MolecularAssembler ) ); + setTileEntiy( TileMolecularAssembler.class ); + } + +} diff --git a/block/mac/BlockCraftingAccelerator.java b/block/mac/BlockCraftingAccelerator.java new file mode 100644 index 00000000..17f97624 --- /dev/null +++ b/block/mac/BlockCraftingAccelerator.java @@ -0,0 +1,19 @@ +package appeng.block.mac; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.mac.TileMolecularAssembler; + +public class BlockCraftingAccelerator extends AEBaseBlock +{ + + public BlockCraftingAccelerator() { + super( BlockCraftingAccelerator.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.MolecularAssembler ) ); + setTileEntiy( TileMolecularAssembler.class ); + } + +} diff --git a/block/mac/BlockHeatVent.java b/block/mac/BlockHeatVent.java new file mode 100644 index 00000000..8501b960 --- /dev/null +++ b/block/mac/BlockHeatVent.java @@ -0,0 +1,19 @@ +package appeng.block.mac; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.mac.TileMolecularAssembler; + +public class BlockHeatVent extends AEBaseBlock +{ + + public BlockHeatVent() { + super( BlockHeatVent.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.MolecularAssembler ) ); + setTileEntiy( TileMolecularAssembler.class ); + } + +} diff --git a/block/mac/BlockPatternProvider.java b/block/mac/BlockPatternProvider.java new file mode 100644 index 00000000..fca0dcf0 --- /dev/null +++ b/block/mac/BlockPatternProvider.java @@ -0,0 +1,19 @@ +package appeng.block.mac; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.mac.TilePatternProvider; + +public class BlockPatternProvider extends AEBaseBlock +{ + + public BlockPatternProvider() { + super( BlockPatternProvider.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.MolecularAssembler ) ); + setTileEntiy( TilePatternProvider.class ); + } + +} diff --git a/block/misc/BlockCharger.java b/block/misc/BlockCharger.java new file mode 100644 index 00000000..35bc4913 --- /dev/null +++ b/block/misc/BlockCharger.java @@ -0,0 +1,155 @@ +package appeng.block.misc; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderBlockCharger; +import appeng.client.render.effects.LightningEffect; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.helpers.ICustomCollision; +import appeng.tile.AEBaseTile; +import appeng.tile.misc.TileCharger; +import appeng.util.Platform; + +public class BlockCharger extends AEBaseBlock implements ICustomCollision +{ + + public BlockCharger() { + super( BlockCharger.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileCharger.class ); + setLightOpacity( 2 ); + isFullSize = false; + isOpaque = false; + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileCharger tc = getTileEntity( w, x, y, z ); + if ( tc != null ) + { + tc.activate( player ); + } + } + + return true; + } + + @Override + protected Class getRenderer() + { + return RenderBlockCharger.class; + } + + @Override + public void randomDisplayTick(World w, int x, int y, int z, Random r) + { + if ( !Configuration.instance.enableEffects ) + return; + + if ( r.nextFloat() < 0.98 ) + return; + + AEBaseTile tile = getTileEntity( w, x, y, z ); + if ( tile instanceof TileCharger ) + { + TileCharger tc = (TileCharger) tile; + if ( AEApi.instance().materials().materialCertusQuartzCrystalCharged.sameAs( tc.getStackInSlot( 0 ) ) ) + { + + double xOff = 0.0; + double yOff = 0.0; + double zOff = 0.0; + + for (int bolts = 0; bolts < 3; bolts++) + { + LightningEffect fx = new LightningEffect( w, xOff + 0.5 + x, yOff + 0.5 + y, zOff + 0.5 + z, 0.0D, 0.0D, 0.0D ); + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + + } + } + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + TileCharger tile = getTileEntity( w, x, y, z ); + if ( tile != null ) + { + double twoPixels = 2.0 / 16.0; + ForgeDirection up = tile.getUp(); + ForgeDirection forward = tile.getForward(); + AxisAlignedBB bb = AxisAlignedBB.getBoundingBox( twoPixels, twoPixels, twoPixels, 1.0 - twoPixels, 1.0 - twoPixels, 1.0 - twoPixels ); + + if ( up.offsetX != 0 ) + { + bb.minX = 0; + bb.maxX = 1; + } + if ( up.offsetY != 0 ) + { + bb.minY = 0; + bb.maxY = 1; + } + if ( up.offsetZ != 0 ) + { + bb.minZ = 0; + bb.maxZ = 1; + } + + switch (forward) + { + case DOWN: + bb.maxY = 1; + break; + case UP: + bb.minY = 0; + break; + case NORTH: + bb.maxZ = 1; + break; + case SOUTH: + bb.minZ = 0; + break; + case EAST: + bb.minX = 0; + break; + case WEST: + bb.maxX = 1; + break; + default: + break; + } + + return Arrays.asList( new AxisAlignedBB[] { bb } ); + } + return Arrays.asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( 0.0, 0, 0.0, 1.0, 1.0, 1.0 ) } ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + out.add( AxisAlignedBB.getAABBPool().getAABB( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 ) ); + } +} diff --git a/block/misc/BlockCondenser.java b/block/misc/BlockCondenser.java new file mode 100644 index 00000000..c91e41d4 --- /dev/null +++ b/block/misc/BlockCondenser.java @@ -0,0 +1,43 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.core.sync.GuiBridge; +import appeng.tile.misc.TileCondenser; +import appeng.util.Platform; + +public class BlockCondenser extends AEBaseBlock +{ + + public BlockCondenser() { + super( BlockCondenser.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileCondenser.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileCondenser tc = getTileEntity( w, x, y, z ); + if ( tc != null && !player.isSneaking() ) + { + Platform.openGUI( player, tc, ForgeDirection.getOrientation(side), GuiBridge.GUI_CONDENSER ); + return true; + } + } + + return true; + } + +} diff --git a/block/misc/BlockInscriber.java b/block/misc/BlockInscriber.java new file mode 100644 index 00000000..6bbe274c --- /dev/null +++ b/block/misc/BlockInscriber.java @@ -0,0 +1,40 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.misc.TileInscriber; +import appeng.util.Platform; + +public class BlockInscriber extends AEBaseBlock +{ + + public BlockInscriber() { + super( BlockInscriber.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Inscriber ) ); + setTileEntiy( TileInscriber.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileInscriber tc = getTileEntity( w, x, y, z ); + if ( tc != null ) + { + tc.activate( player ); + } + } + + return true; + } + +} diff --git a/block/misc/BlockInterface.java b/block/misc/BlockInterface.java new file mode 100644 index 00000000..18e29974 --- /dev/null +++ b/block/misc/BlockInterface.java @@ -0,0 +1,19 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.misc.TileInterface; + +public class BlockInterface extends AEBaseBlock +{ + + public BlockInterface() { + super( BlockInterface.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileInterface.class ); + } + +} diff --git a/block/misc/BlockNetworkEmitter.java b/block/misc/BlockNetworkEmitter.java new file mode 100644 index 00000000..f0ee7f8c --- /dev/null +++ b/block/misc/BlockNetworkEmitter.java @@ -0,0 +1,40 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.misc.TileNetworkEmitter; +import appeng.util.Platform; + +public class BlockNetworkEmitter extends AEBaseBlock +{ + + public BlockNetworkEmitter() { + super( BlockNetworkEmitter.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileNetworkEmitter.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileNetworkEmitter tc = getTileEntity( w, x, y, z ); + if ( tc != null ) + { + tc.activate( player ); + } + } + + return true; + } + +} diff --git a/block/misc/BlockPartitionEditor.java b/block/misc/BlockPartitionEditor.java new file mode 100644 index 00000000..7cab65be --- /dev/null +++ b/block/misc/BlockPartitionEditor.java @@ -0,0 +1,19 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.misc.TilePartitionerEditor; + +public class BlockPartitionEditor extends AEBaseBlock +{ + + public BlockPartitionEditor() { + super( BlockPartitionEditor.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.StorageCells ) ); + setTileEntiy( TilePartitionerEditor.class ); + } + +} diff --git a/block/misc/BlockQuartzCrystalizer.java b/block/misc/BlockQuartzCrystalizer.java new file mode 100644 index 00000000..e7946ed1 --- /dev/null +++ b/block/misc/BlockQuartzCrystalizer.java @@ -0,0 +1,40 @@ +package appeng.block.misc; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.misc.TileQuartzCrystalizer; +import appeng.util.Platform; + +public class BlockQuartzCrystalizer extends AEBaseBlock +{ + + public BlockQuartzCrystalizer() { + super( BlockQuartzCrystalizer.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileQuartzCrystalizer.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileQuartzCrystalizer tc = getTileEntity( w, x, y, z ); + if ( tc != null ) + { + tc.activate( player ); + } + } + + return true; + } + +} diff --git a/block/misc/BlockQuartzTorch.java b/block/misc/BlockQuartzTorch.java new file mode 100644 index 00000000..99ef38bb --- /dev/null +++ b/block/misc/BlockQuartzTorch.java @@ -0,0 +1,128 @@ +package appeng.block.misc; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderQuartzTorch; +import appeng.client.render.effects.LightningEffect; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.helpers.ICustomCollision; +import appeng.helpers.MetaRotation; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class BlockQuartzTorch extends AEBaseBlock implements IOrientableBlock, ICustomCollision +{ + + public BlockQuartzTorch() { + super( BlockQuartzTorch.class, Material.circuits ); + setfeature( EnumSet.of( AEFeature.DecorativeLights ) ); + setLightOpacity( 0 ); + setLightValue( 0.9375F ); + isFullSize = isOpaque = false; + } + + @Override + protected Class getRenderer() + { + return RenderQuartzTorch.class; + } + + @Override + public IOrientable getOrientable(final IBlockAccess w, final int x, final int y, final int z) + { + return new MetaRotation( w, x, y, z ); + } + + private void dropTorch(World w, int x, int y, int z) + { + w.destroyBlock( x, y, z, true ); + w.markBlockForUpdate( x, y, z ); + } + + @Override + public boolean canPlaceBlockAt(World w, int x, int y, int z) + { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + if ( canPlaceAt( w, x, y, z, dir ) ) + return true; + return false; + } + + private boolean canPlaceAt(World w, int x, int y, int z, ForgeDirection dir) + { + return w.isBlockSolidOnSide( x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ, dir.getOpposite(), false ); + } + + @Override + public boolean isValidOrientation(World w, int x, int y, int z, ForgeDirection forward, ForgeDirection up) + { + return canPlaceAt( w, x, y, z, up.getOpposite() ); + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int id) + { + ForgeDirection up = getOrientable( w, x, y, z ).getUp(); + if ( !canPlaceAt( w, x, y, z, up.getOpposite() ) ) + dropTorch( w, x, y, z ); + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + ForgeDirection up = getOrientable( w, x, y, z ).getUp(); + double xOff = -0.3 * up.offsetX; + double yOff = -0.3 * up.offsetY; + double zOff = -0.3 * up.offsetZ; + return Arrays.asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( xOff + 0.3, yOff + 0.3, zOff + 0.3, xOff + 0.7, yOff + 0.7, zOff + 0.7 ) } ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + {/* + * double xOff = -0.15 * getUp().offsetX; double yOff = -0.15 * getUp().offsetY; double zOff = -0.15 * + * getUp().offsetZ; out.add( AxisAlignedBB.getAABBPool().getAABB( xOff + (double) x + 0.15, yOff + (double) y + + * 0.15, zOff + (double) z + 0.15,// ahh xOff + (double) x + 0.85, yOff + (double) y + 0.85, zOff + (double) z + + * 0.85 ) ); + */ + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick(World w, int x, int y, int z, Random r) + { + if ( !Configuration.instance.enableEffects ) + return; + + if ( r.nextFloat() < 0.98 ) + return; + + ForgeDirection up = getOrientable( w, x, y, z ).getUp(); + double xOff = -0.3 * up.offsetX; + double yOff = -0.3 * up.offsetY; + double zOff = -0.3 * up.offsetZ; + for (int bolts = 0; bolts < 3; bolts++) + { + LightningEffect fx = new LightningEffect( w, xOff + 0.5 + x, yOff + 0.5 + y, zOff + 0.5 + z, 0.0D, 0.0D, 0.0D ); + + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + } + +} diff --git a/block/misc/BlockTinyTNT.java b/block/misc/BlockTinyTNT.java new file mode 100644 index 00000000..217edaf1 --- /dev/null +++ b/block/misc/BlockTinyTNT.java @@ -0,0 +1,157 @@ +package appeng.block.misc; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockDispenser; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.item.Item; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Icon; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderTinyTNT; +import appeng.client.render.entity.EntityIds; +import appeng.client.texture.FullIcon; +import appeng.core.AppEng; +import appeng.core.features.AEFeature; +import appeng.entity.EntityTinyTNTPrimed; +import appeng.helpers.DispenserBehaviorTinyTNT; +import appeng.helpers.ICustomCollision; +import cpw.mods.fml.common.registry.EntityRegistry; + +public class BlockTinyTNT extends AEBaseBlock implements ICustomCollision +{ + + public BlockTinyTNT() { + super( BlockTinyTNT.class, Material.tnt ); + setfeature( EnumSet.of( AEFeature.TinyTNT ) ); + setLightOpacity( 3 ); + setBlockBounds( 0.25f, 0.0f, 0.25f, 0.75f, 0.5f, 0.75f ); + isFullSize = isOpaque = false; + + EntityRegistry.registerModEntity( EntityTinyTNTPrimed.class, "EntityTinyTNTPrimed", EntityIds.TINY_TNT, AppEng.instance, 16, 4, true ); + BlockDispenser.dispenseBehaviorRegistry.putObject( Item.itemsList[blockID], new DispenserBehaviorTinyTNT() ); + } + + @Override + protected Class getRenderer() + { + return RenderTinyTNT.class; + } + + @Override + public void registerIcons(IconRegister iconRegistry) + { + // no images required. + } + + @Override + public Icon getIcon(int direction, int metadata) + { + return new FullIcon( Block.tnt.getIcon( direction, metadata ) ); + } + + @Override + public void onEntityCollidedWithBlock(World w, int x, int y, int z, Entity entity) + { + if ( entity instanceof EntityArrow && !w.isRemote ) + { + EntityArrow entityarrow = (EntityArrow) entity; + + if ( entityarrow.isBurning() ) + { + this.startFuse( w, x, y, z, entityarrow.shootingEntity instanceof EntityLivingBase ? (EntityLivingBase) entityarrow.shootingEntity : null ); + w.setBlockToAir( x, y, z ); + } + } + } + + @Override + public void onBlockAdded(World w, int x, int y, int z) + { + super.onBlockAdded( w, x, y, z ); + + if ( w.isBlockIndirectlyGettingPowered( x, y, z ) ) + { + this.startFuse( w, x, y, z, null ); + w.setBlockToAir( x, y, z ); + } + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int id) + { + if ( w.isBlockIndirectlyGettingPowered( x, y, z ) ) + { + this.startFuse( w, x, y, z, null ); + w.setBlockToAir( x, y, z ); + } + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.getCurrentEquippedItem() != null && player.getCurrentEquippedItem().itemID == Item.flintAndSteel.itemID ) + { + this.startFuse( w, x, y, z, player ); + w.setBlockToAir( x, y, z ); + player.getCurrentEquippedItem().damageItem( 1, player ); + return true; + } + else + { + return super.onActivated( w, x, y, z, player, side, hitX, hitY, hitZ ); + } + } + + @Override + public void onBlockDestroyedByExplosion(World w, int x, int y, int z, Explosion exp) + { + if ( !w.isRemote ) + { + EntityTinyTNTPrimed entitytntprimed = new EntityTinyTNTPrimed( w, x + 0.5F, y + 0.5F, z + 0.5F, exp.getExplosivePlacedBy() ); + entitytntprimed.fuse = w.rand.nextInt( entitytntprimed.fuse / 4 ) + entitytntprimed.fuse / 8; + w.spawnEntityInWorld( entitytntprimed ); + } + } + + public void startFuse(World w, int x, int y, int z, EntityLivingBase ignitor) + { + if ( !w.isRemote ) + { + EntityTinyTNTPrimed entitytntprimed = new EntityTinyTNTPrimed( w, x + 0.5F, y + 0.5F, z + 0.5F, ignitor ); + w.spawnEntityInWorld( entitytntprimed ); + w.playSoundAtEntity( entitytntprimed, "random.fuse", 1.0F, 1.0F ); + } + } + + @Override + public boolean canDropFromExplosion(Explosion exp) + { + return false; + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + return Arrays.asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( 0.25, 0, 0.25, 0.75, 0.5, 0.75 ) } ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + out.add( AxisAlignedBB.getAABBPool().getAABB( 0.25, 0, 0.25, 0.75, 0.5, 0.75 ) ); + + } + +} diff --git a/block/misc/BlockVibrationChamber.java b/block/misc/BlockVibrationChamber.java new file mode 100644 index 00000000..b0dc531c --- /dev/null +++ b/block/misc/BlockVibrationChamber.java @@ -0,0 +1,107 @@ +package appeng.block.misc; + +import java.util.EnumSet; +import java.util.Random; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.texture.ExtraTextures; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.sync.GuiBridge; +import appeng.tile.AEBaseTile; +import appeng.tile.misc.TileVibrationChamber; +import appeng.util.Platform; + +public class BlockVibrationChamber extends AEBaseBlock +{ + + public BlockVibrationChamber() { + super( BlockVibrationChamber.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.PowerGen ) ); + setTileEntiy( TileVibrationChamber.class ); + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + if ( player.isSneaking() ) + return false; + + if ( Platform.isServer() ) + { + TileVibrationChamber tc = getTileEntity( w, x, y, z ); + if ( tc != null && !player.isSneaking() ) + { + Platform.openGUI( player, tc, ForgeDirection.getOrientation(side),GuiBridge.GUI_VIBRATIONCHAMBER ); + return true; + } + } + + return true; + } + + @Override + public Icon getBlockTexture(IBlockAccess w, int x, int y, int z, int s) + { + Icon ico = super.getBlockTexture( w, x, y, z, s ); + TileVibrationChamber tvc = getTileEntity( w, x, y, z ); + + if ( tvc != null && tvc.isOn && ico == getRendererInstance().getTexture( ForgeDirection.SOUTH ) ) + { + return ExtraTextures.BlockVibrationChamberFrontOn.getIcon(); + } + + return ico; + } + + @Override + public void randomDisplayTick(World w, int x, int y, int z, Random r) + { + if ( !Configuration.instance.enableEffects ) + return; + + AEBaseTile tile = getTileEntity( w, x, y, z ); + if ( tile instanceof TileVibrationChamber ) + { + TileVibrationChamber tc = (TileVibrationChamber) tile; + if ( tc.isOn ) + { + float f1 = (float) x + 0.5F; + float f2 = (float) y + 0.5F; + float f3 = (float) z + 0.5F; + + ForgeDirection forward = tc.getForward(); + ForgeDirection up = tc.getUp(); + + int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + f1 += forward.offsetX * 0.6; + f2 += forward.offsetY * 0.6; + f3 += forward.offsetZ * 0.6; + + float ox = r.nextFloat(); + float oy = r.nextFloat() * 0.2f; + + f1 += up.offsetX * (-0.3 + oy); + f2 += up.offsetY * (-0.3 + oy); + f3 += up.offsetZ * (-0.3 + oy); + + f1 += west_x * (0.3 * ox - 0.15); + f2 += west_y * (0.3 * ox - 0.15); + f3 += west_z * (0.3 * ox - 0.15); + + w.spawnParticle( "smoke", (double) f1, (double) f2, (double) f3, 0.0D, 0.0D, 0.0D ); + w.spawnParticle( "flame", (double) f1, (double) f2, (double) f3, 0.0D, 0.0D, 0.0D ); + } + } + } + +} diff --git a/block/networking/BlockCableBus.java b/block/networking/BlockCableBus.java new file mode 100644 index 00000000..9662d412 --- /dev/null +++ b/block/networking/BlockCableBus.java @@ -0,0 +1,234 @@ +package appeng.block.networking; + +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.SelectedPart; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RendererCableBus; +import appeng.client.texture.CableBusTextures; +import appeng.core.Api; +import appeng.core.AppEng; +import appeng.core.features.AEFeature; +import appeng.integration.abstraction.IFMP; +import appeng.parts.CableBusContainer; +import appeng.tile.AEBaseTile; +import appeng.tile.networking.TileCableBus; + +public class BlockCableBus extends AEBaseBlock +{ + + public BlockCableBus() { + super( BlockCableBus.class, Material.glass ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setLightOpacity( 0 ); + isFullSize = isOpaque = false; + } + + @Override + public boolean recolourBlock(World world, int x, int y, int z, ForgeDirection side, int colour) + { + try + { + return cb( world, x, y, z ).recolourBlock( side, colour ); + } + catch (Throwable t) + { + } + return false; + } + + @Override + public void randomDisplayTick(World world, int x, int y, int z, Random r) + { + CableBusContainer cb = cb( world, x, y, z ); + if ( cb != null ) + cb.randomDisplayTick( world, x, y, z, r ); + } + + @Override + public int getLightValue(IBlockAccess world, int x, int y, int z) + { + CableBusContainer cb = cb( world, x, y, z ); + if ( cb != null ) + return cb.getLightValue(); + return 0; + } + + @Override + public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z) + { + Vec3 v3 = target.hitVec.addVector( -x, -y, -z ); + SelectedPart sp = cb( world, x, y, z ).selectPart( v3 ); + if ( sp != null ) + { + if ( sp.part != null ) + return sp.part.getItemStack( false ); + if ( sp.facade != null ) + return sp.facade.getItemStack(); + } + return null; + } + + @Override + public boolean isBlockReplaceable(World world, int x, int y, int z) + { + return cb( world, x, y, z ).isEmpty(); + } + + @Override + public boolean removeBlockByPlayer(World world, EntityPlayer player, int x, int y, int z) + { + if ( player.capabilities.isCreativeMode ) + { + AEBaseTile tile = getTileEntity( world, x, y, z ); + if ( tile != null ) + tile.dropItems = false; + // maybe ray trace? + } + return super.removeBlockByPlayer( world, player, x, y, z ); + } + + @Override + public Icon getBlockTexture(IBlockAccess w, int x, int y, int z, int s) + { + return getIcon( s, 0 ); + } + + @Override + public Icon getIcon(int direction, int metadata) + { + Icon i = super.getIcon( direction, metadata ); + if ( i != null ) + return i; + return CableBusTextures.getMissing(); + } + + private CableBusContainer cb(IBlockAccess w, int x, int y, int z) + { + TileEntity te = w.getBlockTileEntity( x, y, z ); + if ( te instanceof TileCableBus ) + return ((TileCableBus) te).cb; + + if ( AppEng.instance.isIntegrationEnabled( "FMP" ) ) + return ((IFMP) AppEng.instance.getIntegration( "FMP" )).getCableContainer( te ); + + return null; + } + + @Override + protected Class getRenderer() + { + return RendererCableBus.class; + } + + @Override + public void registerIcons(IconRegister iconRegistry) + { + + } + + private int rs(int side) + { + int s = 0; + switch (side) + { + case -1: + s = 1; + break; + case 1: + s = 2; + break; + case 2: + s = 5; + break; + case 3: + s = 3; + break; + case 4: + s = 4; + break; + default: + } + return s; + } + + @Override + public boolean canProvidePower() + { + return true; + } + + @Override + public boolean isBlockSolidOnSide(World w, int x, int y, int z, ForgeDirection side) + { + return cb( w, x, y, z ).isSolidOnSide( side ); + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int meh) + { + cb( w, x, y, z ).onNeighborChanged(); + // kinda works + /* + * if ( cb( w, x, y, z ).isEmpty() ) { w.setBlockToAir( x, y, z ); } + */ + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) + { + return cb( w, x, y, z ).activate( player, w.getWorldVec3Pool().getVecFromPool( hitX, hitY, hitZ ) ); + } + + @Override + public void onEntityCollidedWithBlock(World w, int x, int y, int z, Entity e) + { + cb( w, x, y, z ).onEntityCollision( e ); + } + + @Override + public boolean canConnectRedstone(IBlockAccess w, int x, int y, int z, int side) + { + return cb( w, x, y, z ).canConnectRedstone( ForgeDirection.getOrientation( rs( side ) ) ); + } + + @Override + public int isProvidingWeakPower(IBlockAccess w, int x, int y, int z, int side) + { + return cb( w, x, y, z ).isProvidingWeakPower( ForgeDirection.getOrientation( side ) ); + } + + @Override + public int isProvidingStrongPower(IBlockAccess w, int x, int y, int z, int side) + { + return cb( w, x, y, z ).isProvidingStrongPower( ForgeDirection.getOrientation( side ) ); + } + + @Override + public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + + } + + public void setupTile() + { + setTileEntiy( Api.instance.partHelper.getCombinedInstance( TileCableBus.class.getName() ) ); + } + +} diff --git a/block/networking/BlockController.java b/block/networking/BlockController.java new file mode 100644 index 00000000..d409691e --- /dev/null +++ b/block/networking/BlockController.java @@ -0,0 +1,36 @@ +package appeng.block.networking; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderBlockController; +import appeng.core.features.AEFeature; +import appeng.tile.networking.TileController; + +public class BlockController extends AEBaseBlock +{ + + public BlockController() { + super( BlockController.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileController.class ); + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int id_junk) + { + TileController tc = getTileEntity( w, x, y, z ); + if ( tc != null ) + tc.onNeighborChange( false ); + } + + @Override + protected Class getRenderer() + { + return RenderBlockController.class; + } + +} diff --git a/block/networking/BlockCreativeEnergyCell.java b/block/networking/BlockCreativeEnergyCell.java new file mode 100644 index 00000000..c9824445 --- /dev/null +++ b/block/networking/BlockCreativeEnergyCell.java @@ -0,0 +1,19 @@ +package appeng.block.networking; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.networking.TileCreativeEnergyCell; + +public class BlockCreativeEnergyCell extends AEBaseBlock +{ + + public BlockCreativeEnergyCell() { + super( BlockCreativeEnergyCell.class, Material.glass ); + setfeature( EnumSet.of( AEFeature.Creative ) ); + setTileEntiy( TileCreativeEnergyCell.class ); + } + +} diff --git a/block/networking/BlockDenseEnergyCell.java b/block/networking/BlockDenseEnergyCell.java new file mode 100644 index 00000000..405a9bf3 --- /dev/null +++ b/block/networking/BlockDenseEnergyCell.java @@ -0,0 +1,51 @@ +package appeng.block.networking; + +import java.util.EnumSet; + +import net.minecraft.util.Icon; +import appeng.client.texture.ExtraTextures; +import appeng.core.features.AEFeature; +import appeng.tile.networking.TileDenseEnergyCell; + +public class BlockDenseEnergyCell extends BlockEnergyCell +{ + + @Override + public double getMaxPower() + { + return 200000.0 * 8.0; + } + + public BlockDenseEnergyCell() { + super( BlockDenseEnergyCell.class ); + setfeature( EnumSet.of( AEFeature.DenseEnergyCells ) ); + setTileEntiy( TileDenseEnergyCell.class ); + } + + @Override + public Icon getIcon(int direction, int metadata) + { + switch (metadata) + { + case 0: + return ExtraTextures.MEDenseEnergyCell0.getIcon(); + case 1: + return ExtraTextures.MEDenseEnergyCell1.getIcon(); + case 2: + return ExtraTextures.MEDenseEnergyCell2.getIcon(); + case 3: + return ExtraTextures.MEDenseEnergyCell3.getIcon(); + case 4: + return ExtraTextures.MEDenseEnergyCell4.getIcon(); + case 5: + return ExtraTextures.MEDenseEnergyCell5.getIcon(); + case 6: + return ExtraTextures.MEDenseEnergyCell6.getIcon(); + case 7: + return ExtraTextures.MEDenseEnergyCell7.getIcon(); + + } + return super.getIcon( direction, metadata ); + } + +} diff --git a/block/networking/BlockEnergyAcceptor.java b/block/networking/BlockEnergyAcceptor.java new file mode 100644 index 00000000..731beb5f --- /dev/null +++ b/block/networking/BlockEnergyAcceptor.java @@ -0,0 +1,19 @@ +package appeng.block.networking; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.networking.TileEnergyAcceptor; + +public class BlockEnergyAcceptor extends AEBaseBlock +{ + + public BlockEnergyAcceptor() { + super( BlockEnergyAcceptor.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileEnergyAcceptor.class ); + } + +} diff --git a/block/networking/BlockEnergyCell.java b/block/networking/BlockEnergyCell.java new file mode 100644 index 00000000..133cfec2 --- /dev/null +++ b/block/networking/BlockEnergyCell.java @@ -0,0 +1,88 @@ +package appeng.block.networking; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.material.Material; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.Icon; +import appeng.block.AEBaseBlock; +import appeng.block.AEBaseItemBlockChargeable; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderBlockEnergyCube; +import appeng.client.texture.ExtraTextures; +import appeng.core.features.AEFeature; +import appeng.tile.networking.TileEnergyCell; +import appeng.util.Platform; + +public class BlockEnergyCell extends AEBaseBlock +{ + + public double getMaxPower() + { + return 200000.0; + } + + public BlockEnergyCell(Class c) { + super( c, Material.glass ); + } + + public BlockEnergyCell() { + this( BlockEnergyCell.class ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setTileEntiy( TileEnergyCell.class ); + } + + @Override + public void getSubBlocks(int id, CreativeTabs tab, List list) + { + super.getSubBlocks( id, tab, list ); + + ItemStack charged = new ItemStack( this, 1 ); + NBTTagCompound tag = Platform.openNbtData( charged ); + tag.setDouble( "internalCurrentPower", getMaxPower() ); + tag.setDouble( "internalMaxPower", getMaxPower() ); + list.add( charged ); + } + + @Override + protected Class getRenderer() + { + return RenderBlockEnergyCube.class; + } + + @Override + public Icon getIcon(int direction, int metadata) + { + switch (metadata) + { + case 0: + return ExtraTextures.MEEnergyCell0.getIcon(); + case 1: + return ExtraTextures.MEEnergyCell1.getIcon(); + case 2: + return ExtraTextures.MEEnergyCell2.getIcon(); + case 3: + return ExtraTextures.MEEnergyCell3.getIcon(); + case 4: + return ExtraTextures.MEEnergyCell4.getIcon(); + case 5: + return ExtraTextures.MEEnergyCell5.getIcon(); + case 6: + return ExtraTextures.MEEnergyCell6.getIcon(); + case 7: + return ExtraTextures.MEEnergyCell7.getIcon(); + + } + return super.getIcon( direction, metadata ); + } + + @Override + public Class getItemBlockClass() + { + return AEBaseItemBlockChargeable.class; + } + +} diff --git a/block/networking/BlockWireless.java b/block/networking/BlockWireless.java new file mode 100644 index 00000000..b48ba353 --- /dev/null +++ b/block/networking/BlockWireless.java @@ -0,0 +1,169 @@ +package appeng.block.networking; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Icon; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderBlockWireless; +import appeng.core.features.AEFeature; +import appeng.helpers.ICustomCollision; +import appeng.tile.networking.TileWireless; + +public class BlockWireless extends AEBaseBlock implements ICustomCollision +{ + + public BlockWireless() { + super( BlockWireless.class, Material.glass ); + setfeature( EnumSet.of( AEFeature.Core, AEFeature.WirelessAccessTerminal ) ); + setTileEntiy( TileWireless.class ); + setLightOpacity( 0 ); + isFullSize = false; + isOpaque = false; + } + + @Override + protected Class getRenderer() + { + return RenderBlockWireless.class; + } + + @Override + public Icon getIcon(int direction, int metadata) + { + return super.getIcon( direction, metadata ); + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + TileWireless tile = getTileEntity( w, x, y, z ); + if ( tile != null ) + { + ForgeDirection forward = tile.getForward(); + + double minX = 0; + double minY = 0; + double minZ = 0; + double maxX = 1; + double maxY = 1; + double maxZ = 1; + + switch (forward) + { + case DOWN: + minZ = minX = 3.0 / 16.0; + maxZ = maxX = 13.0 / 16.0; + maxY = 1.0; + minY = 5.0 / 16.0; + break; + case EAST: + minZ = minY = 3.0 / 16.0; + maxZ = maxY = 13.0 / 16.0; + maxX = 11.0 / 16.0; + minX = 0.0; + break; + case NORTH: + minY = minX = 3.0 / 16.0; + maxY = maxX = 13.0 / 16.0; + maxZ = 1.0; + minZ = 5.0 / 16.0; + break; + case SOUTH: + minY = minX = 3.0 / 16.0; + maxY = maxX = 13.0 / 16.0; + maxZ = 11.0 / 16.0; + minZ = 0.0; + break; + case UP: + minZ = minX = 3.0 / 16.0; + maxZ = maxX = 13.0 / 16.0; + maxY = 11.0 / 16.0; + minY = 0.0; + break; + case WEST: + minZ = minY = 3.0 / 16.0; + maxZ = maxY = 13.0 / 16.0; + maxX = 1.0; + minX = 5.0 / 16.0; + break; + default: + break; + } + + return Arrays.asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( minX, minY, minZ, maxX, maxY, maxZ ) } ); + } + return Arrays.asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( 0.0, 0, 0.0, 1.0, 1.0, 1.0 ) } ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + TileWireless tile = getTileEntity( w, x, y, z ); + if ( tile != null ) + { + ForgeDirection forward = tile.getForward(); + + double minX = 0; + double minY = 0; + double minZ = 0; + double maxX = 1; + double maxY = 1; + double maxZ = 1; + + switch (forward) + { + case DOWN: + minZ = minX = 3.0 / 16.0; + maxZ = maxX = 13.0 / 16.0; + maxY = 1.0; + minY = 5.0 / 16.0; + break; + case EAST: + minZ = minY = 3.0 / 16.0; + maxZ = maxY = 13.0 / 16.0; + maxX = 11.0 / 16.0; + minX = 0.0; + break; + case NORTH: + minY = minX = 3.0 / 16.0; + maxY = maxX = 13.0 / 16.0; + maxZ = 1.0; + minZ = 5.0 / 16.0; + break; + case SOUTH: + minY = minX = 3.0 / 16.0; + maxY = maxX = 13.0 / 16.0; + maxZ = 11.0 / 16.0; + minZ = 0.0; + break; + case UP: + minZ = minX = 3.0 / 16.0; + maxZ = maxX = 13.0 / 16.0; + maxY = 11.0 / 16.0; + minY = 0.0; + break; + case WEST: + minZ = minY = 3.0 / 16.0; + maxZ = maxY = 13.0 / 16.0; + maxX = 1.0; + minX = 5.0 / 16.0; + break; + default: + break; + } + + out.add( AxisAlignedBB.getAABBPool().getAABB( minX, minY, minZ, maxX, maxY, maxZ ) ); + } + else + out.add( AxisAlignedBB.getAABBPool().getAABB( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 ) ); + } + +} diff --git a/block/qnb/BlockQuantumLinkChamber.java b/block/qnb/BlockQuantumLinkChamber.java new file mode 100644 index 00000000..d0f27918 --- /dev/null +++ b/block/qnb/BlockQuantumLinkChamber.java @@ -0,0 +1,31 @@ +package appeng.block.qnb; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderQNB; +import appeng.core.features.AEFeature; +import appeng.tile.qnb.TileQuantumBridge; + +public class BlockQuantumLinkChamber extends AEBaseBlock +{ + + public BlockQuantumLinkChamber() { + super( BlockQuantumLinkChamber.class, Material.glass ); + setfeature( EnumSet.of( AEFeature.QuantumNetworkBridge ) ); + setTileEntiy( TileQuantumBridge.class ); + float shave = 2.0f / 16.0f; + setBlockBounds( shave, shave, shave, 1.0f - shave, 1.0f - shave, 1.0f - shave ); + setLightOpacity( 0 ); + isFullSize = isOpaque = false; + } + + @Override + protected Class getRenderer() + { + return RenderQNB.class; + } + +} diff --git a/block/qnb/BlockQuantumRing.java b/block/qnb/BlockQuantumRing.java new file mode 100644 index 00000000..370a84d7 --- /dev/null +++ b/block/qnb/BlockQuantumRing.java @@ -0,0 +1,31 @@ +package appeng.block.qnb; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderQNB; +import appeng.core.features.AEFeature; +import appeng.tile.qnb.TileQuantumBridge; + +public class BlockQuantumRing extends AEBaseBlock +{ + + public BlockQuantumRing() { + super( BlockQuantumRing.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.QuantumNetworkBridge ) ); + setTileEntiy( TileQuantumBridge.class ); + float shave = 2.0f / 16.0f; + setBlockBounds( shave, shave, shave, 1.0f - shave, 1.0f - shave, 1.0f - shave ); + setLightOpacity( 1 ); + isFullSize = isOpaque = false; + } + + @Override + protected Class getRenderer() + { + return RenderQNB.class; + } + +} diff --git a/block/solids/BlockMatrixFrame.java b/block/solids/BlockMatrixFrame.java new file mode 100644 index 00000000..373e8f58 --- /dev/null +++ b/block/solids/BlockMatrixFrame.java @@ -0,0 +1,37 @@ +package appeng.block.solids; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.material.Material; +import net.minecraft.creativetab.CreativeTabs; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderNull; +import appeng.core.features.AEFeature; + +public class BlockMatrixFrame extends AEBaseBlock +{ + + public BlockMatrixFrame() { + super( BlockMatrixFrame.class, Material.portal ); + setfeature( EnumSet.of( AEFeature.SpatialIO ) ); + setResistance( 6000000.0F ); + setBlockUnbreakable(); + setLightOpacity( 0 ); + isOpaque = false; + } + + @Override + protected Class getRenderer() + { + return RenderNull.class; + } + + @Override + public void getSubBlocks(int id, CreativeTabs tab, List list) + { + + } + +} diff --git a/block/solids/BlockQuartz.java b/block/solids/BlockQuartz.java new file mode 100644 index 00000000..424b1c58 --- /dev/null +++ b/block/solids/BlockQuartz.java @@ -0,0 +1,17 @@ +package appeng.block.solids; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; + +public class BlockQuartz extends AEBaseBlock +{ + + public BlockQuartz() { + super( BlockQuartz.class, Material.rock ); + setfeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks ) ); + } + +} diff --git a/block/solids/BlockQuartzChiseled.java b/block/solids/BlockQuartzChiseled.java new file mode 100644 index 00000000..f24fa45d --- /dev/null +++ b/block/solids/BlockQuartzChiseled.java @@ -0,0 +1,17 @@ +package appeng.block.solids; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; + +public class BlockQuartzChiseled extends AEBaseBlock +{ + + public BlockQuartzChiseled() { + super( BlockQuartzChiseled.class, Material.rock ); + setfeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks ) ); + } + +} diff --git a/block/solids/BlockQuartzGlass.java b/block/solids/BlockQuartzGlass.java new file mode 100644 index 00000000..64b0937c --- /dev/null +++ b/block/solids/BlockQuartzGlass.java @@ -0,0 +1,47 @@ +package appeng.block.solids; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderQuartzGlass; +import appeng.core.features.AEFeature; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class BlockQuartzGlass extends AEBaseBlock +{ + + public BlockQuartzGlass() { + this( BlockQuartzGlass.class ); + } + + @Override + @SideOnly(Side.CLIENT) + public Class getRenderer() + { + return RenderQuartzGlass.class; + } + + @Override + public boolean shouldSideBeRendered(IBlockAccess w, int x, int y, int z, int side) + { + if ( w.getBlockMaterial( x, y, z ) == Material.glass ) + { + if ( Block.blocksList[w.getBlockId( x, y, z )].getRenderType() == this.getRenderType() ) + return false; + } + return super.shouldSideBeRendered( w, x, y, z, side ); + } + + public BlockQuartzGlass(Class c) { + super( c, Material.glass ); + setfeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks ) ); + setLightOpacity( 0 ); + isOpaque = false; + } + +} diff --git a/block/solids/BlockQuartzLamp.java b/block/solids/BlockQuartzLamp.java new file mode 100644 index 00000000..631a345c --- /dev/null +++ b/block/solids/BlockQuartzLamp.java @@ -0,0 +1,41 @@ +package appeng.block.solids; + +import java.util.EnumSet; +import java.util.Random; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.world.World; +import appeng.client.render.effects.VibrantEffect; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class BlockQuartzLamp extends BlockQuartzGlass +{ + + public BlockQuartzLamp() { + super( BlockQuartzLamp.class ); + setfeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks, AEFeature.DecorativeLights ) ); + setLightValue( 1.0f ); + setTextureName( "BlockQuartzGlass" ); + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick(World w, int x, int y, int z, Random r) + { + if ( !Configuration.instance.enableEffects ) + return; + + double d0 = (double) (r.nextFloat() - 0.5F) * 0.96D; + double d1 = (double) (r.nextFloat() - 0.5F) * 0.96D; + double d2 = (double) (r.nextFloat() - 0.5F) * 0.96D; + + VibrantEffect fx = new VibrantEffect( w, 0.5 + x + d0, 0.5 + y + d1, 0.5 + z + d2, 0.0D, 0.0D, 0.0D ); + + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + +} diff --git a/block/solids/BlockQuartzPillar.java b/block/solids/BlockQuartzPillar.java new file mode 100644 index 00000000..f6589f8e --- /dev/null +++ b/block/solids/BlockQuartzPillar.java @@ -0,0 +1,27 @@ +package appeng.block.solids; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.world.IBlockAccess; +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.helpers.MetaRotation; + +public class BlockQuartzPillar extends AEBaseBlock implements IOrientableBlock +{ + + public BlockQuartzPillar() { + super( BlockQuartzPillar.class, Material.rock ); + setfeature( EnumSet.of( AEFeature.DecorativeQuartzBlocks ) ); + } + + @Override + public IOrientable getOrientable(final IBlockAccess w, final int x, final int y, final int z) + { + return new MetaRotation( w, x, y, z ); + } + +} diff --git a/block/solids/OreQuartz.java b/block/solids/OreQuartz.java new file mode 100644 index 00000000..4167b7d6 --- /dev/null +++ b/block/solids/OreQuartz.java @@ -0,0 +1,129 @@ +package appeng.block.solids; + +import java.util.EnumSet; +import java.util.Random; + +import net.minecraft.block.material.Material; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MathHelper; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderQuartzOre; +import appeng.core.features.AEFeature; +import appeng.helpers.LocationRotation; + +public class OreQuartz extends AEBaseBlock implements IOrientableBlock +{ + + public int boostBrightnessLow; + public int boostBrightnessHigh; + public boolean enhanceBrightness; + + public OreQuartz(Class self) { + super( self, Material.rock ); + setfeature( EnumSet.of( AEFeature.Core ) ); + setHardness( 3.0F ); + setResistance( 5.0F ); + boostBrightnessLow = 0; + boostBrightnessHigh = 1; + enhanceBrightness = false; + } + + @Override + protected Class getRenderer() + { + return RenderQuartzOre.class; + } + + @Override + public int getMixedBrightnessForBlock(IBlockAccess par1iBlockAccess, int par2, int par3, int par4) + { + int j1 = super.getMixedBrightnessForBlock( par1iBlockAccess, par2, par3, par4 ); + if ( enhanceBrightness ) + { + j1 = Math.max( j1 >> 20, j1 >> 4 ); + + if ( j1 > 4 ) + j1 += boostBrightnessHigh; + else + j1 += boostBrightnessLow; + + if ( j1 > 15 ) + j1 = 15; + return j1 << 20 | j1 << 4; + } + return j1; + } + + public OreQuartz() { + this( OreQuartz.class ); + } + + ItemStack getItemDropped() + { + return AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ); + } + + @Override + public IOrientable getOrientable(final IBlockAccess w, final int x, final int y, final int z) + { + return new LocationRotation( w, x, y, z ); + } + + @Override + public int idDropped(int id, Random rand, int meta) + { + return getItemDropped().itemID; + } + + @Override + public int damageDropped(int id) + { + return getItemDropped().getItemDamage(); + } + + @Override + public int quantityDropped(Random rand) + { + return 1 + rand.nextInt( 2 ); + } + + @Override + public int quantityDroppedWithBonus(int fortune, Random rand) + { + if ( fortune > 0 && this.blockID != this.idDropped( 0, rand, fortune ) ) + { + int j = rand.nextInt( fortune + 2 ) - 1; + + if ( j < 0 ) + { + j = 0; + } + + return this.quantityDropped( rand ) * (j + 1); + } + else + { + return this.quantityDropped( rand ); + } + } + + @Override + public void dropBlockAsItemWithChance(World w, int x, int y, int z, int blockid, float something, int meta) + { + super.dropBlockAsItemWithChance( w, x, y, z, blockid, something, meta ); + + if ( this.idDropped( blockid, w.rand, meta ) != this.blockID ) + { + int xp = MathHelper.getRandomIntegerInRange( w.rand, 2, 5 ); + + this.dropXpOnBlockBreak( w, x, y, z, xp ); + } + } + +} diff --git a/block/solids/OreQuartzCharged.java b/block/solids/OreQuartzCharged.java new file mode 100644 index 00000000..1ccedf8d --- /dev/null +++ b/block/solids/OreQuartzCharged.java @@ -0,0 +1,70 @@ +package appeng.block.solids; + +import java.util.Random; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.client.render.effects.ChargedOreEffect; +import appeng.core.Configuration; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class OreQuartzCharged extends OreQuartz +{ + + public OreQuartzCharged() { + super( OreQuartzCharged.class ); + boostBrightnessLow = 2; + boostBrightnessHigh = 5; + } + + @Override + ItemStack getItemDropped() + { + return AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ); + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick(World w, int x, int y, int z, Random r) + { + if ( !Configuration.instance.enableEffects ) + return; + + double xOff = (double) (r.nextFloat()); + double yOff = (double) (r.nextFloat()); + double zOff = (double) (r.nextFloat()); + + switch (r.nextInt( 6 )) + { + case 0: + xOff = -0.01; + break; + case 1: + yOff = -0.01; + break; + case 2: + xOff = -0.01; + break; + case 3: + zOff = -0.01; + break; + case 4: + xOff = 1.01; + break; + case 5: + yOff = 1.01; + break; + case 6: + zOff = 1.01; + break; + } + + ChargedOreEffect fx = new ChargedOreEffect( w, x + xOff, y + yOff, z + zOff, 0.0f, 0.0f, 0.0f ); + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + +} diff --git a/block/spatial/BlockSpatialIOPort.java b/block/spatial/BlockSpatialIOPort.java new file mode 100644 index 00000000..201e431a --- /dev/null +++ b/block/spatial/BlockSpatialIOPort.java @@ -0,0 +1,28 @@ +package appeng.block.spatial; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.spatial.TileSpatialIOPort; + +public class BlockSpatialIOPort extends AEBaseBlock +{ + + public BlockSpatialIOPort() { + super( BlockSpatialIOPort.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.SpatialIO ) ); + setTileEntiy( TileSpatialIOPort.class ); + } + + @Override + public final void onNeighborBlockChange(World w, int x, int y, int z, int junk) + { + TileSpatialIOPort te = getTileEntity( w, x, y, z ); + if ( te != null ) + te.updateRedstoneState(); + } + +} diff --git a/block/spatial/BlockSpatialPylon.java b/block/spatial/BlockSpatialPylon.java new file mode 100644 index 00000000..b17c221a --- /dev/null +++ b/block/spatial/BlockSpatialPylon.java @@ -0,0 +1,46 @@ +package appeng.block.spatial; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderSpatialPylon; +import appeng.core.features.AEFeature; +import appeng.tile.spatial.TileSpatialPylon; + +public class BlockSpatialPylon extends AEBaseBlock +{ + + public BlockSpatialPylon() { + super( BlockSpatialPylon.class, Material.glass ); + setfeature( EnumSet.of( AEFeature.SpatialIO ) ); + setTileEntiy( TileSpatialPylon.class ); + } + + @Override + public void onNeighborBlockChange(World w, int x, int y, int z, int junk) + { + TileSpatialPylon tsp = getTileEntity( w, x, y, z ); + if ( tsp != null ) + tsp.onNeighborBlockChange(); + } + + @Override + public int getLightValue(IBlockAccess w, int x, int y, int z) + { + TileSpatialPylon tsp = getTileEntity( w, x, y, z ); + if ( tsp != null ) + return tsp.getLightValue(); + return super.getLightValue( w, x, y, z ); + } + + @Override + protected Class getRenderer() + { + return RenderSpatialPylon.class; + } + +} diff --git a/block/storage/BlockChest.java b/block/storage/BlockChest.java new file mode 100644 index 00000000..3863be70 --- /dev/null +++ b/block/storage/BlockChest.java @@ -0,0 +1,86 @@ +package appeng.block.storage; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderMEChest; +import appeng.core.features.AEFeature; +import appeng.core.localization.PlayerMessages; +import appeng.core.sync.GuiBridge; +import appeng.tile.storage.TileChest; +import appeng.util.Platform; + +public class BlockChest extends AEBaseBlock +{ + + public BlockChest() { + super( BlockChest.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.StorageCells, AEFeature.MEChest ) ); + setTileEntiy( TileChest.class ); + } + + @Override + protected Class getRenderer() + { + return RenderMEChest.class; + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer p, int side, float hitX, float hitY, float hitZ) + { + TileChest tg = getTileEntity( w, x, y, z ); + if ( tg != null && !p.isSneaking() ) + { + if ( Platform.isClient() ) + return true; + + if ( side != tg.getUp().ordinal() ) + { + Platform.openGUI( p, tg, ForgeDirection.getOrientation( side ), GuiBridge.GUI_CHEST ); + } + else if ( tg.isPowered() ) + { + ItemStack cell = tg.getStackInSlot( 1 ); + if ( cell != null ) + { + ICellHandler ch = AEApi.instance().registries().cell().getHander( cell ); + + List ih = tg.getCellArray( StorageChannel.ITEMS ); + if ( ch != null && ih != null && ih.size() == 1 ) + { + IMEInventoryHandler mine = ih.get( 0 ); + ch.openChestGui( p, tg, ch, mine, cell, StorageChannel.ITEMS ); + return true; + } + + List fh = tg.getCellArray( StorageChannel.FLUIDS ); + if ( ch != null && fh != null && ih.size() == 1 ) + { + IMEInventoryHandler mine = fh.get( 0 ); + ch.openChestGui( p, tg, ch, mine, cell, StorageChannel.FLUIDS ); + return true; + } + } + + p.sendChatToPlayer( PlayerMessages.ChestCannotReadStorageCell.get() ); + } + else + p.sendChatToPlayer( PlayerMessages.MachineNotPowered.get() ); + + return true; + } + + return false; + } +} diff --git a/block/storage/BlockDrive.java b/block/storage/BlockDrive.java new file mode 100644 index 00000000..49a89454 --- /dev/null +++ b/block/storage/BlockDrive.java @@ -0,0 +1,44 @@ +package appeng.block.storage; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.blocks.RenderDrive; +import appeng.core.features.AEFeature; +import appeng.core.sync.GuiBridge; +import appeng.tile.storage.TileDrive; +import appeng.util.Platform; + +public class BlockDrive extends AEBaseBlock +{ + + public BlockDrive() { + super( BlockDrive.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.StorageCells, AEFeature.MEDrive ) ); + setTileEntiy( TileDrive.class ); + } + + @Override + protected Class getRenderer() + { + return RenderDrive.class; + } + + @Override + public boolean onActivated(World w, int x, int y, int z, EntityPlayer p, int side, float hitX, float hitY, float hitZ) + { + TileDrive tg = getTileEntity( w, x, y, z ); + if ( tg != null && !p.isSneaking() ) + { + Platform.openGUI( p, tg, ForgeDirection.getOrientation(side),GuiBridge.GUI_DRIVE ); + return true; + } + return false; + } + +} diff --git a/block/storage/BlockIOPort.java b/block/storage/BlockIOPort.java new file mode 100644 index 00000000..41d8a3a6 --- /dev/null +++ b/block/storage/BlockIOPort.java @@ -0,0 +1,19 @@ +package appeng.block.storage; + +import java.util.EnumSet; + +import net.minecraft.block.material.Material; +import appeng.block.AEBaseBlock; +import appeng.core.features.AEFeature; +import appeng.tile.storage.TileIOPort; + +public class BlockIOPort extends AEBaseBlock +{ + + public BlockIOPort() { + super( BlockIOPort.class, Material.iron ); + setfeature( EnumSet.of( AEFeature.StorageCells, AEFeature.IOPort ) ); + setTileEntiy( TileIOPort.class ); + } + +} diff --git a/client/ClientHelper.java b/client/ClientHelper.java new file mode 100644 index 00000000..9e8a0390 --- /dev/null +++ b/client/ClientHelper.java @@ -0,0 +1,81 @@ +package appeng.client; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.TESRWrapper; +import appeng.client.render.WorldRender; +import appeng.client.render.entity.RenderTinyTNTPrimed; +import appeng.client.texture.CableBusTextures; +import appeng.client.texture.ExtraTextures; +import appeng.entity.EntityTinyTNTPrimed; +import appeng.server.ServerHelper; +import appeng.util.Platform; +import cpw.mods.fml.client.registry.ClientRegistry; +import cpw.mods.fml.client.registry.RenderingRegistry; + +public class ClientHelper extends ServerHelper +{ + + @Override + public void init() + { + MinecraftForge.EVENT_BUS.register( this ); + + RenderingRegistry.registerBlockHandler( WorldRender.instance ); + RenderManager.instance.entityRenderMap.put( EntityTinyTNTPrimed.class, new RenderTinyTNTPrimed() ); + } + + @ForgeSubscribe + public void updateTextureSheet(TextureStitchEvent.Pre ev) + { + if ( ev.map.textureType == 0 ) + { + for (ExtraTextures et : ExtraTextures.values()) + et.registerIcon( ev.map ); + + for (CableBusTextures cb : CableBusTextures.values()) + cb.registerIcon( ev.map ); + } + } + + @Override + public World getWorld() + { + if ( Platform.isClient() ) + return Minecraft.getMinecraft().theWorld; + else + return super.getWorld(); + } + + @Override + public void bindTileEntitySpecialRenderer(Class tile, AEBaseBlock blk) + { + BaseBlockRender bbr = blk.getRendererInstance().rendererInstance; + if ( bbr.hasTESR ) + ClientRegistry.bindTileEntitySpecialRenderer( tile, new TESRWrapper( bbr ) ); + } + + @Override + public List getPlayers() + { + if ( Platform.isClient() ) + { + List o = new ArrayList(); + o.add( Minecraft.getMinecraft().thePlayer ); + return o; + } + else + return super.getPlayers(); + } + +} \ No newline at end of file diff --git a/client/gui/AEBaseGui.java b/client/gui/AEBaseGui.java new file mode 100644 index 00000000..aa5d2146 --- /dev/null +++ b/client/gui/AEBaseGui.java @@ -0,0 +1,292 @@ +package appeng.client.gui; + +import java.io.IOException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import appeng.api.storage.data.IAEItemStack; +import appeng.client.gui.widgets.GuiScrollbar; +import appeng.client.gui.widgets.ITooltip; +import appeng.client.me.InternalSlotME; +import appeng.client.me.SlotME; +import appeng.core.sync.packets.PacketInventoryAction; +import appeng.helpers.InventoryAction; +import cpw.mods.fml.common.network.PacketDispatcher; + +public abstract class AEBaseGui extends GuiContainer +{ + + protected List meSlots = new LinkedList(); + protected GuiScrollbar myScrollBar = null; + + public AEBaseGui(Container container) { + super( container ); + } + + @Override + public void initGui() + { + super.initGui(); + + Iterator i = inventorySlots.inventorySlots.iterator(); + while (i.hasNext()) + if ( i.next() instanceof SlotME ) + i.remove(); + + for (InternalSlotME me : meSlots) + inventorySlots.inventorySlots.add( new SlotME( me ) ); + } + + @Override + public void handleMouseInput() + { + super.handleMouseInput(); + + if ( myScrollBar != null ) + { + int i = Mouse.getEventDWheel(); + if ( i != 0 ) + myScrollBar.wheel( i ); + } + } + + @Override + protected void handleMouseClick(Slot slot, int slotIdx, int ctrlDown, int key) + { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + + if ( slot instanceof SlotME ) + { + InventoryAction action = null; + IAEItemStack stack = null; + + switch (key) + { + case 0: // pickup / set-down. + action = ctrlDown == 1 ? InventoryAction.SPLIT_OR_PLACESINGLE : InventoryAction.PICKUP_OR_SETDOWN; + stack = ((SlotME) slot).getAEStack(); + break; + case 1: + action = InventoryAction.SHIFT_CLICK; + stack = ((SlotME) slot).getAEStack(); + break; + + case 3: // creative dupe: + if ( player.capabilities.isCreativeMode ) + { + IAEItemStack slotItem = ((SlotME) slot).getAEStack(); + if ( slotItem != null ) + { + action = InventoryAction.CREATIVE_DUPLICATE; + stack = slotItem; + } + } + break; + + default: + case 4: // drop item: + case 6: + } + + if ( action != null ) + { + PacketInventoryAction p; + try + { + p = new PacketInventoryAction( action, slotIdx, stack ); + PacketDispatcher.sendPacketToServer( p.getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + return; + } + + super.handleMouseClick( slot, slotIdx, ctrlDown, key ); + } + + @Override + public void drawScreen(int mouse_x, int mouse_y, float btn) + { + super.drawScreen( mouse_x, mouse_y, btn ); + + boolean hasClicked = Mouse.isButtonDown( 0 ); + if ( hasClicked && myScrollBar != null ) + myScrollBar.click( this, mouse_x - guiLeft, mouse_y - guiTop ); + + for (Object c : buttonList) + { + if ( c instanceof ITooltip ) + { + ITooltip tooltip = (ITooltip) c; + int x = tooltip.xPos(); // ((GuiImgButton) c).xPosition; + int y = tooltip.yPos(); // ((GuiImgButton) c).yPosition; + + if ( x < mouse_x && x + tooltip.getWidth() > mouse_x ) + { + if ( y < mouse_y && y + tooltip.getHeight() > mouse_y ) + { + String msg = tooltip.getMsg(); + if ( msg != null ) + drawTooltip( x + 8, y + 4, 0, msg ); + } + } + } + } + } + + public void drawTooltip(int par2, int par3, int forceWidth, String Msg) + { + GL11.glPushAttrib( GL11.GL_ALL_ATTRIB_BITS ); + GL11.glDisable( GL12.GL_RESCALE_NORMAL ); + RenderHelper.disableStandardItemLighting(); + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL11.GL_DEPTH_TEST ); + String[] var4 = Msg.split( "\n" ); + + if ( var4.length > 0 ) + { + int var5 = 0; + int var6; + int var7; + + for (var6 = 0; var6 < var4.length; ++var6) + { + var7 = fontRenderer.getStringWidth( (String) var4[var6] ); + + if ( var7 > var5 ) + { + var5 = var7; + } + } + + var6 = par2 + 12; + var7 = par3 - 12; + int var9 = 8; + + if ( var4.length > 1 ) + { + var9 += 2 + (var4.length - 1) * 10; + } + + if ( this.guiTop + var7 + var9 + 6 > this.height ) + { + var7 = this.height - var9 - this.guiTop - 6; + } + + if ( forceWidth > 0 ) + var5 = forceWidth; + + this.zLevel = 300.0F; + itemRenderer.zLevel = 300.0F; + int var10 = -267386864; + this.drawGradientRect( var6 - 3, var7 - 4, var6 + var5 + 3, var7 - 3, var10, var10 ); + this.drawGradientRect( var6 - 3, var7 + var9 + 3, var6 + var5 + 3, var7 + var9 + 4, var10, var10 ); + this.drawGradientRect( var6 - 3, var7 - 3, var6 + var5 + 3, var7 + var9 + 3, var10, var10 ); + this.drawGradientRect( var6 - 4, var7 - 3, var6 - 3, var7 + var9 + 3, var10, var10 ); + this.drawGradientRect( var6 + var5 + 3, var7 - 3, var6 + var5 + 4, var7 + var9 + 3, var10, var10 ); + int var11 = 1347420415; + int var12 = (var11 & 16711422) >> 1 | var11 & -16777216; + this.drawGradientRect( var6 - 3, var7 - 3 + 1, var6 - 3 + 1, var7 + var9 + 3 - 1, var11, var12 ); + this.drawGradientRect( var6 + var5 + 2, var7 - 3 + 1, var6 + var5 + 3, var7 + var9 + 3 - 1, var11, var12 ); + this.drawGradientRect( var6 - 3, var7 - 3, var6 + var5 + 3, var7 - 3 + 1, var11, var11 ); + this.drawGradientRect( var6 - 3, var7 + var9 + 2, var6 + var5 + 3, var7 + var9 + 3, var12, var12 ); + + for (int var13 = 0; var13 < var4.length; ++var13) + { + String var14 = (String) var4[var13]; + + if ( var13 == 0 ) + { + var14 = "\u00a7" + Integer.toHexString( 15 ) + var14; + } + else + { + var14 = "\u00a77" + var14; + } + + this.fontRenderer.drawStringWithShadow( var14, var6, var7, -1 ); + + if ( var13 == 0 ) + { + var7 += 2; + } + + var7 += 10; + } + + this.zLevel = 0.0F; + itemRenderer.zLevel = 0.0F; + } + GL11.glPopAttrib(); + } + + public abstract void drawBG(int offsetX, int offsetY, int mouseX, int mouseY); + + public abstract void drawFG(int offsetX, int offsetY, int mouseX, int mouseY); + + public void bindTexture(String base, String file) + { + ResourceLocation loc = new ResourceLocation( base, "textures/" + file ); + this.mc.getTextureManager().bindTexture( loc ); + } + + public void bindTexture(String file) + { + ResourceLocation loc = new ResourceLocation( "appliedenergistics2", "textures/" + file ); + this.mc.getTextureManager().bindTexture( loc ); + } + + protected void drawItem(int x, int y, ItemStack is) + { + this.zLevel = 100.0F; + itemRenderer.zLevel = 100.0F; + + GL11.glEnable( GL11.GL_LIGHTING ); + GL11.glEnable( GL12.GL_RESCALE_NORMAL ); + RenderHelper.enableGUIStandardItemLighting(); + itemRenderer.renderItemAndEffectIntoGUI( this.fontRenderer, this.mc.renderEngine, is, x, y ); + GL11.glDisable( GL11.GL_LIGHTING ); + + itemRenderer.zLevel = 0.0F; + this.zLevel = 0.0F; + } + + @Override + final protected void drawGuiContainerBackgroundLayer(float f, int x, int y) + { + int ox = guiLeft; // (width - xSize) / 2; + int oy = guiTop; // (height - ySize) / 2; + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + drawBG( ox, oy, x, y ); + } + + @Override + final protected void drawGuiContainerForegroundLayer(int x, int y) + { + int ox = guiLeft; // (width - xSize) / 2; + int oy = guiTop; // (height - ySize) / 2; + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + drawFG( ox, oy, x, y ); + if ( myScrollBar != null ) + myScrollBar.draw( this ); + } + +} diff --git a/client/gui/AEBaseMEGui.java b/client/gui/AEBaseMEGui.java new file mode 100644 index 00000000..5e9a0edd --- /dev/null +++ b/client/gui/AEBaseMEGui.java @@ -0,0 +1,315 @@ +package appeng.client.gui; + +import java.text.NumberFormat; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + +import org.lwjgl.opengl.GL11; + +import appeng.api.storage.data.IAEItemStack; +import appeng.client.me.SlotME; +import appeng.client.render.AppEngRenderItem; +import appeng.container.slot.AppEngSlot; +import appeng.container.slot.AppEngSlot.hasCalculatedValidness; +import appeng.container.slot.SlotDisabled; +import appeng.container.slot.SlotInaccessable; +import appeng.container.slot.SlotOutput; +import appeng.container.slot.SlotRestrictedInput; +import appeng.core.AELog; +import appeng.core.Configuration; + +public abstract class AEBaseMEGui extends AEBaseGui +{ + + public AEBaseMEGui(Container container) { + super( container ); + } + + // @Override - NEI + public List handleItemTooltip(ItemStack stack, int mousex, int mousey, List currenttip) + { + if ( stack != null ) + { + Slot s = getSlot( mousex, mousey ); + if ( s instanceof SlotME ) + { + int BigNumber = Configuration.instance.useTerminalUseLargeFont() ? 999 : 9999; + + IAEItemStack myStack = null; + + try + { + SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } + catch (Throwable _) + { + } + + if ( myStack != null ) + { + if ( myStack.getStackSize() > BigNumber || (myStack.getStackSize() > 1 && stack.isItemDamaged()) ) + currenttip.add( "\u00a77Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() ) ); + + if ( myStack.getCountRequestable() > 0 ) + currenttip.add( "\u00a77Items Requestable: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() ) ); + } + else if ( stack.stackSize > BigNumber || (stack.stackSize > 1 && stack.isItemDamaged()) ) + { + currenttip.add( "\u00a77Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( stack.stackSize ) ); + } + } + else + currenttip.add( StatCollector.translateToLocal( "AppEng.Gui.Whitelisted" ) ); + } + return currenttip; + } + + // Vanillia version... + @Override + protected void drawItemStackTooltip(ItemStack stack, int x, int y) + { + Slot s = getSlot( x, y ); + if ( s instanceof SlotME && stack != null ) + { + int BigNumber = Configuration.instance.useTerminalUseLargeFont() ? 999 : 9999; + + IAEItemStack myStack = null; + + try + { + SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } + catch (Throwable _) + { + } + + if ( myStack != null ) + { + List currenttip = stack.getTooltip( this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips ); + + if ( myStack.getStackSize() > BigNumber || (myStack.getStackSize() > 1 && stack.isItemDamaged()) ) + currenttip.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() ) ); + + if ( myStack.getCountRequestable() > 0 ) + currenttip.add( "Items Requestable: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() ) ); + + drawTooltip( x, y, 0, join( currenttip, "\n" ) ); + } + else if ( stack != null && stack.stackSize > BigNumber ) + { + List var4 = stack.getTooltip( this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips ); + var4.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( stack.stackSize ) ); + drawTooltip( x, y, 0, join( var4, "\n" ) ); + return; + } + } + super.drawItemStackTooltip( stack, x, y ); + } + + static String join(Collection s, String delimiter) + { + StringBuilder builder = new StringBuilder(); + Iterator iter = s.iterator(); + while (iter.hasNext()) + { + builder.append( iter.next() ); + if ( !iter.hasNext() ) + { + break; + } + builder.append( delimiter ); + } + return builder.toString(); + } + + private Slot getSlot(int mousex, int mousey) + { + for (int j1 = 0; j1 < this.inventorySlots.inventorySlots.size(); ++j1) + { + Slot slot = (Slot) this.inventorySlots.inventorySlots.get( j1 ); + if ( isPointInRegion( slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mousex, mousey ) ) + { + return slot; + } + } + + return null; + } + + private void safeDrawSlot(Slot s) + { + try + { + super.drawSlotInventory( s ); + } + catch (Exception err) + { + Tessellator tessellator = Tessellator.instance; + if ( tessellator.isDrawing ) + tessellator.draw(); + } + } + + AppEngRenderItem aeri = new AppEngRenderItem(); + + @Override + protected void drawSlotInventory(Slot s) + { + if ( s instanceof SlotME ) + { + RenderItem pIR = itemRenderer; + itemRenderer = aeri; + try + { + this.zLevel = 100.0F; + itemRenderer.zLevel = 100.0F; + + if ( ! isPowered() ) + { + GL11.glDisable( GL11.GL_LIGHTING ); + super.drawRect( s.xDisplayPosition, s.yDisplayPosition, 16 + s.xDisplayPosition, 16 + s.yDisplayPosition, 0x66111111 ); + GL11.glEnable( GL11.GL_LIGHTING ); + } + + this.zLevel = 0.0F; + itemRenderer.zLevel = 0.0F; + + if ( s instanceof SlotME ) + aeri.aestack = ((SlotME) s).getAEStack(); + else + aeri.aestack = null; + + safeDrawSlot( s ); + } + catch (Exception err) + { + AELog.warning( "[AppEng] AE prevented crash while drawing slot: " + err.toString() ); + if ( Tessellator.instance.isDrawing ) + Tessellator.instance.draw(); + } + itemRenderer = pIR; + return; + } + else + { + try + { + ItemStack is = s.getStack(); + if ( s instanceof AppEngSlot && (((AppEngSlot) s).renderIconWithItem() || is == null) ) + { + AppEngSlot aes = (AppEngSlot) s; + if ( aes.getIcon() >= 0 ) + { + bindTexture( "guis/states.png" ); + + GL11.glPushAttrib( GL11.GL_ALL_ATTRIB_BITS ); + Tessellator tessellator = Tessellator.instance; + try + { + int uv_y = (int) Math.floor( aes.getIcon() / 16 ); + int uv_x = aes.getIcon() - uv_y * 16; + + GL11.glEnable( GL11.GL_BLEND ); + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_TEXTURE_2D ); + GL11.glBlendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA ); + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + float par1 = aes.xDisplayPosition; + float par2 = aes.yDisplayPosition; + float par3 = uv_x * 16; + float par4 = uv_y * 16; + float par5 = 16; + float par6 = 16; + + float f = 0.00390625F; + float f1 = 0.00390625F; + tessellator.startDrawingQuads(); + tessellator.setColorRGBA_F( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ); + tessellator.addVertexWithUV( (double) (par1 + 0), (double) (par2 + par6), (double) this.zLevel, (double) ((float) (par3 + 0) * f), + (double) ((float) (par4 + par6) * f1) ); + tessellator.addVertexWithUV( (double) (par1 + par5), (double) (par2 + par6), (double) this.zLevel, + (double) ((float) (par3 + par5) * f), (double) ((float) (par4 + par6) * f1) ); + tessellator.addVertexWithUV( (double) (par1 + par5), (double) (par2 + 0), (double) this.zLevel, + (double) ((float) (par3 + par5) * f), (double) ((float) (par4 + 0) * f1) ); + tessellator.addVertexWithUV( (double) (par1 + 0), (double) (par2 + 0), (double) this.zLevel, (double) ((float) (par3 + 0) * f), + (double) ((float) (par4 + 0) * f1) ); + tessellator.setColorRGBA_F( 1.0f, 1.0f, 1.0f, 1.0f ); + tessellator.draw(); + } + catch (Exception err) + { + if ( tessellator.isDrawing ) + tessellator.draw(); + } + GL11.glPopAttrib(); + } + } + + if ( is != null && s instanceof AppEngSlot ) + { + if ( ((AppEngSlot) s).isValid == hasCalculatedValidness.NotAvailable ) + { + boolean isValid = s.isItemValid( is ) || s instanceof SlotOutput || s instanceof SlotDisabled || s instanceof SlotInaccessable; + if ( isValid && s instanceof SlotRestrictedInput ) + { + try + { + isValid = ((SlotRestrictedInput) s).isValid( is, this.mc.theWorld ); + } + catch (Exception err) + { + err.printStackTrace(); + } + } + ((AppEngSlot) s).isValid = isValid ? hasCalculatedValidness.Valid : hasCalculatedValidness.Invalid; + } + + if ( ((AppEngSlot) s).isValid == hasCalculatedValidness.Invalid ) + { + this.zLevel = 100.0F; + itemRenderer.zLevel = 100.0F; + + GL11.glDisable( GL11.GL_LIGHTING ); + super.drawRect( s.xDisplayPosition, s.yDisplayPosition, 16 + s.xDisplayPosition, 16 + s.yDisplayPosition, 0x66ff6666 ); + GL11.glEnable( GL11.GL_LIGHTING ); + + this.zLevel = 0.0F; + itemRenderer.zLevel = 0.0F; + } + } + + if ( s instanceof AppEngSlot ) + { + ((AppEngSlot) s).isDisplay = true; + safeDrawSlot( s ); + } + else + safeDrawSlot( s ); + + return; + } + catch (Exception err) + { + AELog.warning( "[AppEng] AE prevented crash while drawing slot: " + err.toString() ); + } + } + // do the usual for non-ME Slots. + safeDrawSlot( s ); + } + + private boolean isPowered() { + return true; + } + +} \ No newline at end of file diff --git a/client/gui/GuiNull.java b/client/gui/GuiNull.java new file mode 100644 index 00000000..f23cfea5 --- /dev/null +++ b/client/gui/GuiNull.java @@ -0,0 +1,23 @@ +package appeng.client.gui; + +import net.minecraft.inventory.Container; + +public class GuiNull extends AEBaseGui +{ + + public GuiNull(Container container) { + super( container ); + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + } + +} diff --git a/client/gui/implementations/GuiChest.java b/client/gui/implementations/GuiChest.java new file mode 100644 index 00000000..c487e34d --- /dev/null +++ b/client/gui/implementations/GuiChest.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerChest; +import appeng.core.localization.GuiText; +import appeng.tile.storage.TileChest; + +public class GuiChest extends AEBaseGui +{ + + public GuiChest(InventoryPlayer inventoryPlayer, TileChest te) { + super( new ContainerChest( inventoryPlayer, te ) ); + this.ySize = 166; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/chest.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.Chest.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiCondenser.java b/client/gui/implementations/GuiCondenser.java new file mode 100644 index 00000000..9d0c85bf --- /dev/null +++ b/client/gui/implementations/GuiCondenser.java @@ -0,0 +1,82 @@ +package appeng.client.gui.implementations; + +import java.io.IOException; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import appeng.api.config.Settings; +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiProgressBar; +import appeng.client.gui.widgets.GuiProgressBar.Direction; +import appeng.container.implementations.ContainerCondenser; +import appeng.core.localization.GuiText; +import appeng.core.sync.packets.PacketConfigButton; +import appeng.tile.misc.TileCondenser; +import cpw.mods.fml.common.network.PacketDispatcher; + +public class GuiCondenser extends AEBaseGui +{ + + ContainerCondenser cvc; + GuiProgressBar pb; + GuiImgButton mode; + + public GuiCondenser(InventoryPlayer inventoryPlayer, TileCondenser te) { + super( new ContainerCondenser( inventoryPlayer, te ) ); + cvc = (ContainerCondenser) inventorySlots; + this.ySize = 197; + } + + @Override + protected void actionPerformed(GuiButton btn) + { + super.actionPerformed( btn ); + + if ( mode == btn ) + { + try + { + PacketDispatcher.sendPacketToServer( (new PacketConfigButton( Settings.CONDENSER_OUTPUT )).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + @Override + public void initGui() + { + super.initGui(); + + pb = new GuiProgressBar( "guis/condenser.png", 120 + guiLeft, 25 + guiTop, 178, 25, 6, 18, Direction.VERTICAL ); + pb.TitleName = GuiText.StoredEnergy.getLocal(); + + mode = new GuiImgButton( 128 + guiLeft, 52 + guiTop, Settings.CONDENSER_OUTPUT, cvc.output ); + + this.buttonList.add( pb ); + this.buttonList.add( mode ); + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/condenser.png" ); + + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.Condenser.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + + mode.set( cvc.output ); + pb.max = cvc.requiredEnergy; + pb.current = cvc.storedPower; + } + +} diff --git a/client/gui/implementations/GuiDrive.java b/client/gui/implementations/GuiDrive.java new file mode 100644 index 00000000..d8db233e --- /dev/null +++ b/client/gui/implementations/GuiDrive.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerDrive; +import appeng.core.localization.GuiText; +import appeng.tile.storage.TileDrive; + +public class GuiDrive extends AEBaseGui +{ + + public GuiDrive(InventoryPlayer inventoryPlayer, TileDrive te) { + super( new ContainerDrive( inventoryPlayer, te ) ); + this.ySize = 199; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/drive.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.Drive.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiGrinder.java b/client/gui/implementations/GuiGrinder.java new file mode 100644 index 00000000..febdd648 --- /dev/null +++ b/client/gui/implementations/GuiGrinder.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerGrinder; +import appeng.core.localization.GuiText; +import appeng.tile.grindstone.TileGrinder; + +public class GuiGrinder extends AEBaseGui +{ + + public GuiGrinder(InventoryPlayer inventoryPlayer, TileGrinder te) { + super( new ContainerGrinder( inventoryPlayer, te ) ); + this.ySize = 176; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/grinder.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.GrindStone.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiLevelEmitter.java b/client/gui/implementations/GuiLevelEmitter.java new file mode 100644 index 00000000..233e0ef5 --- /dev/null +++ b/client/gui/implementations/GuiLevelEmitter.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerLevelEmitter; +import appeng.core.localization.GuiText; +import appeng.parts.automation.PartLevelEmitter; + +public class GuiLevelEmitter extends AEBaseGui +{ + + public GuiLevelEmitter(InventoryPlayer inventoryPlayer, PartLevelEmitter te) { + super( new ContainerLevelEmitter( inventoryPlayer, te ) ); + this.ySize = 199; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/lvlemitter.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.LevelEmitter.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiMEMonitorable.java b/client/gui/implementations/GuiMEMonitorable.java new file mode 100644 index 00000000..184bc503 --- /dev/null +++ b/client/gui/implementations/GuiMEMonitorable.java @@ -0,0 +1,162 @@ +package appeng.client.gui.implementations; + +import java.util.List; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.entity.player.InventoryPlayer; +import appeng.api.config.Settings; +import appeng.api.implementations.IMEChest; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.storage.data.IAEItemStack; +import appeng.client.gui.AEBaseMEGui; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiScrollbar; +import appeng.client.me.InternalSlotME; +import appeng.client.me.ItemRepo; +import appeng.container.implementations.ContainerMEMonitorable; +import appeng.container.slot.AppEngSlot; +import appeng.core.Configuration; +import appeng.core.localization.GuiText; +import appeng.parts.reporting.PartTerminal; +import appeng.util.Platform; + +public class GuiMEMonitorable extends AEBaseMEGui +{ + + GuiTextField searchField; + ItemRepo repo; + + GuiText myName; + int rows = 0; + + public GuiMEMonitorable(InventoryPlayer inventoryPlayer, IStorageMonitorable te) { + super( new ContainerMEMonitorable( inventoryPlayer, null ) ); + myScrollBar = new GuiScrollbar(); + repo = new ItemRepo( myScrollBar ); + xSize = 195; + ySize = 204; + + if ( te instanceof IMEChest ) + myName = GuiText.Chest; + else if ( te instanceof PartTerminal ) + myName = GuiText.Terminal; + + } + + public void postUpdate(List list) + { + for (IAEItemStack is : list) + repo.postUpdate( is ); + + repo.updateView(); + setScrollBar(); + } + + private void setScrollBar() + { + myScrollBar.setTop( 18 ).setLeft( 175 ).setHeight( rows * 18 - 2 ); + myScrollBar.setRange( 0, (repo.size() + 8) / 9 - rows, Math.max( 1, rows / 6 ) ); + } + + @Override + public void initGui() + { + int NEI = 0; + int top = 4; + int extraSpace = height - 114 - NEI - top; + rows = (int) Math.floor( extraSpace / 18 ); + + meSlots.clear(); + for (int y = 0; y < rows; y++) + { + for (int x = 0; x < 9; x++) + { + meSlots.add( new InternalSlotME( repo, x + y * 9, 9 + x * 18, 18 + y * 18 ) ); + } + } + + super.initGui(); + // full size : 204 + // extra slots : 72 + // slot 18 + + this.ySize = 114 + rows * 18; + this.guiTop = top; + + buttonList.add( new GuiImgButton( this.guiLeft - 18, guiTop + 8, Settings.SORT_BY, Configuration.instance.settings.getSetting( Settings.SORT_BY ) ) ); + buttonList.add( new GuiImgButton( this.guiLeft - 18, guiTop + 28, Settings.SORT_DIRECTION, Configuration.instance.settings + .getSetting( Settings.SORT_DIRECTION ) ) ); + + searchField = new GuiTextField( this.fontRenderer, this.guiLeft + 82, this.guiTop + 6, 89, this.fontRenderer.FONT_HEIGHT ); + searchField.setEnableBackgroundDrawing( false ); + searchField.setMaxStringLength( 25 ); + searchField.setTextColor( 0xFFFFFF ); + searchField.setVisible( true ); + searchField.setFocused( true ); + + setScrollBar(); + + for (Object s : inventorySlots.inventorySlots) + { + if ( s instanceof AppEngSlot ) + { + ((AppEngSlot) s).yDisplayPosition = ((AppEngSlot) s).defY + ySize - 78 - guiTop; + } + } + } + + @Override + protected void actionPerformed(GuiButton btn) + { + if ( btn instanceof GuiImgButton ) + { + GuiImgButton iBtn = (GuiImgButton) btn; + Enum cv = iBtn.getCurrentValue(); + + Enum next = Platform.nextEnum( cv ); + Configuration.instance.settings.putSetting( iBtn.getSetting(), next ); + iBtn.set( next ); + repo.updateView(); + } + } + + @Override + protected void keyTyped(char character, int key) + { + if ( !this.checkHotbarKeys( key ) ) + { + if ( searchField.textboxKeyTyped( character, key ) ) + { + repo.searchString = this.searchField.getText(); + repo.updateView(); + } + else + { + super.keyTyped( character, key ); + } + } + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/terminal.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, 18 ); + + for (int x = 0; x < rows; x++) + this.drawTexturedModalRect( offsetX, offsetY + 18 + x * 18, 0, 18, xSize, 18 ); + + this.drawTexturedModalRect( offsetX, offsetY + 16 + rows * 18, 0, 106, xSize, 98 ); + + searchField.drawTextBox(); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( myName.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiNetworkStatus.java b/client/gui/implementations/GuiNetworkStatus.java new file mode 100644 index 00000000..8f6ba77c --- /dev/null +++ b/client/gui/implementations/GuiNetworkStatus.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.tileentity.TileEntity; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerNetworkStatus; +import appeng.core.localization.GuiText; + +public class GuiNetworkStatus extends AEBaseGui +{ + + public GuiNetworkStatus(InventoryPlayer inventoryPlayer, TileEntity te) { + super( new ContainerNetworkStatus( inventoryPlayer, (TileEntity) te ) ); + this.ySize = 199; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/networkstatus.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.NetworkStatus.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiSpatialIOPort.java b/client/gui/implementations/GuiSpatialIOPort.java new file mode 100644 index 00000000..71f35ee4 --- /dev/null +++ b/client/gui/implementations/GuiSpatialIOPort.java @@ -0,0 +1,31 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.client.gui.AEBaseGui; +import appeng.container.implementations.ContainerSpatialIOPort; +import appeng.core.localization.GuiText; +import appeng.tile.spatial.TileSpatialIOPort; + +public class GuiSpatialIOPort extends AEBaseGui +{ + + public GuiSpatialIOPort(InventoryPlayer inventoryPlayer, TileSpatialIOPort te) { + super( new ContainerSpatialIOPort( inventoryPlayer, te ) ); + this.ySize = 199; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/spatialio.png" ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.SpatialIOPort.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + } + +} diff --git a/client/gui/implementations/GuiVibrationChamber.java b/client/gui/implementations/GuiVibrationChamber.java new file mode 100644 index 00000000..904649aa --- /dev/null +++ b/client/gui/implementations/GuiVibrationChamber.java @@ -0,0 +1,66 @@ +package appeng.client.gui.implementations; + +import net.minecraft.entity.player.InventoryPlayer; + +import org.lwjgl.opengl.GL11; + +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiProgressBar; +import appeng.client.gui.widgets.GuiProgressBar.Direction; +import appeng.container.implementations.ContainerVibrationChamber; +import appeng.core.localization.GuiText; +import appeng.tile.misc.TileVibrationChamber; + +public class GuiVibrationChamber extends AEBaseGui +{ + + ContainerVibrationChamber cvc; + GuiProgressBar pb; + + public GuiVibrationChamber(InventoryPlayer inventoryPlayer, TileVibrationChamber te) { + super( new ContainerVibrationChamber( inventoryPlayer, te ) ); + cvc = (ContainerVibrationChamber) inventorySlots; + this.ySize = 166; + } + + @Override + public void initGui() + { + super.initGui(); + + pb = new GuiProgressBar( "guis/vibchamber.png", 99, 36, 176, 14, 6, 18, Direction.VERTICAL ); + this.buttonList.add( pb ); + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) + { + bindTexture( "guis/vibchamber.png" ); + pb.xPosition = 99 + guiLeft; + pb.yPosition = 36 + guiTop; + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) + { + fontRenderer.drawString( GuiText.VibrationChamber.getLocal(), 8, 6, 4210752 ); + fontRenderer.drawString( GuiText.inventory.getLocal(), 8, ySize - 96 + 3, 4210752 ); + + int k = 25; + int l = -15; + + pb.max = 200; + pb.current = cvc.burnProgress > 0 ? cvc.burnSpeed : 0; + pb.FullMsg = (cvc.aePerTick * pb.current / 100) + " ae/t"; + + if ( cvc.burnProgress > 0 ) + { + int i1 = cvc.burnProgress; + bindTexture( "guis/vibchamber.png" ); + GL11.glColor3f( 1, 1, 1 ); + this.drawTexturedModalRect( k + 56, l + 36 + 12 - i1, 176, 12 - i1, 14, i1 + 2 ); + } + } + +} diff --git a/client/gui/widgets/GuiImgButton.java b/client/gui/widgets/GuiImgButton.java new file mode 100644 index 00000000..a260e488 --- /dev/null +++ b/client/gui/widgets/GuiImgButton.java @@ -0,0 +1,321 @@ +package appeng.client.gui.widgets; + +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.util.StatCollector; + +import org.lwjgl.opengl.GL11; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.ActionItems; +import appeng.api.config.CondenserOuput; +import appeng.api.config.FullnessMode; +import appeng.api.config.FuzzyMode; +import appeng.api.config.IncludeExclude; +import appeng.api.config.MatchingMode; +import appeng.api.config.OperationMode; +import appeng.api.config.PowerUnits; +import appeng.api.config.RedstoneMode; +import appeng.api.config.RelativeDirection; +import appeng.api.config.SearchBoxMode; +import appeng.api.config.Settings; +import appeng.api.config.SortDir; +import appeng.api.config.SortOrder; +import appeng.api.config.ViewItems; +import appeng.api.config.YesNo; +import appeng.client.texture.ExtraTextures; + +public class GuiImgButton extends GuiButton implements ITooltip +{ + + class EnumPair + { + + Enum setting; + Enum value; + + EnumPair(Enum a, Enum b) { + setting = a; + value = b; + } + + @Override + public int hashCode() + { + return setting.hashCode() ^ value.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + EnumPair d = (EnumPair) obj; + return d.setting.equals( setting ) && d.value.equals( value ); + } + + }; + + class BtnAppearance + { + + public int index; + public String DisplayName; + public String DisplayValue; + }; + + public boolean halfSize = false; + public String FillVar; + + private final Enum buttonSetting; + private Enum currentValue; + + static private Map Appearances; + + private void registerApp(int icon, Settings setting, Enum val, String dn, String dv) + { + BtnAppearance a = new BtnAppearance(); + a.DisplayName = dn; + a.DisplayValue = dv; + a.index = icon; + Appearances.put( new EnumPair( setting, val ), a ); + } + + public GuiImgButton(int x, int y, Enum idx, Enum val) { + super( 0, 0, 16, "" ); + buttonSetting = idx; + currentValue = val; + xPosition = x; + yPosition = y; + width = 16; + height = 16; + + if ( Appearances == null ) + { + Appearances = new HashMap(); + registerApp( 16 * 7 + 0, Settings.CONDENSER_OUTPUT, CondenserOuput.TRASH, "AppEng.GuiITooltip.CondenserOutput", "AppEng.GuiITooltip.Trash" ); + registerApp( 16 * 7 + 1, Settings.CONDENSER_OUTPUT, CondenserOuput.MATTER_BALLS, "AppEng.GuiITooltip.CondenserOutput", + "AppEng.GuiITooltip.MatterBalls" ); + registerApp( 16 * 7 + 2, Settings.CONDENSER_OUTPUT, CondenserOuput.SINGULARITY, "AppEng.GuiITooltip.CondenserOutput", + "AppEng.GuiITooltip.Singularity" ); + + registerApp( 16 * 9 + 1, Settings.ACCESS, AccessRestriction.READ, "AppEng.GuiITooltip.IOMode", "AppEng.GuiITooltip.Read" ); + registerApp( 16 * 9 + 0, Settings.ACCESS, AccessRestriction.WRITE, "AppEng.GuiITooltip.IOMode", "AppEng.GuiITooltip.Write" ); + registerApp( 16 * 9 + 2, Settings.ACCESS, AccessRestriction.READ_WRITE, "AppEng.GuiITooltip.IOMode", "AppEng.GuiITooltip.ReadWrite" ); + + registerApp( 16 * 10 + 0, Settings.POWER_UNITS, PowerUnits.AE, "AppEng.GuiITooltip.PowerUnits", "AppEng.GuiITooltip.AEUnits" ); + registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, "AppEng.GuiITooltip.PowerUnits", "AppEng.GuiITooltip.EUUnits" ); + registerApp( 16 * 10 + 2, Settings.POWER_UNITS, PowerUnits.MJ, "AppEng.GuiITooltip.PowerUnits", "AppEng.GuiITooltip.MJUnits" ); + registerApp( 16 * 10 + 3, Settings.POWER_UNITS, PowerUnits.KJ, "AppEng.GuiITooltip.PowerUnits", "AppEng.GuiITooltip.UEUnits" ); + registerApp( 16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.WA, "AppEng.GuiITooltip.PowerUnits", "AppEng.GuiITooltip.WUnits" ); + + registerApp( 3, Settings.REDSTONE_INPUT, RedstoneMode.IGNORE, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.AlwaysActive" ); + registerApp( 0, Settings.REDSTONE_INPUT, RedstoneMode.LOW_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.ActiveWithoutSignal" ); + registerApp( 1, Settings.REDSTONE_INPUT, RedstoneMode.HIGH_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.ActiveWithSignal" ); + registerApp( 2, Settings.REDSTONE_INPUT, RedstoneMode.SIGNAL_PULSE, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.ActiveOnPulse" ); + + registerApp( 3, Settings.REDSTONE_INPUT, RedstoneMode.IGNORE, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.AlwaysActive" ); + registerApp( 0, Settings.REDSTONE_INPUT, RedstoneMode.LOW_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.ActiveWithoutSignal" ); + registerApp( 1, Settings.REDSTONE_INPUT, RedstoneMode.HIGH_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.ActiveWithSignal" ); + + registerApp( 0, Settings.REDSTONE_OUTPUT, RedstoneMode.LOW_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.EmitLevelsBelow" ); + registerApp( 1, Settings.REDSTONE_OUTPUT, RedstoneMode.HIGH_SIGNAL, "AppEng.GuiITooltip.RedstoneMode", "AppEng.GuiITooltip.EmitLevelAbove" ); + + registerApp( 16 * 8 + 2, Settings.INCLUSION, IncludeExclude.WHITELIST, "AppEng.Gui.Whitelisted", "AppEng.Gui.WhitelistedDesc" ); + registerApp( 16 * 8 + 3, Settings.INCLUSION, IncludeExclude.BLACKLIST, "AppEng.Gui.Blacklisted", "AppEng.Gui.BlacklistedDesc" ); + + registerApp( 34, Settings.COMPARISON, MatchingMode.FUZZY, "AppEng.GuiITooltip.MatchingMode", "AppEng.GuiITooltip.MatchingFuzzy" ); + registerApp( 32, Settings.COMPARISON, MatchingMode.PRECISE, "AppEng.GuiITooltip.MatchingMode", "AppEng.GuiITooltip.MatchingExact" ); + + registerApp( 50, Settings.OPERATION_MODE, OperationMode.EMPTY, "AppEng.GuiITooltip.TransferDirection", "AppEng.GuiITooltip.TransferToNetwork" ); + registerApp( 51, Settings.OPERATION_MODE, OperationMode.FILL, "AppEng.GuiITooltip.TransferDirection", "AppEng.GuiITooltip.TransferToStorageCell" ); + + registerApp( 51, Settings.IO_DIRECTION, RelativeDirection.LEFT, "AppEng.GuiITooltip.TransferDirection", "AppEng.GuiITooltip.TransferToStorageCell" ); + registerApp( 50, Settings.IO_DIRECTION, RelativeDirection.RIGHT, "AppEng.GuiITooltip.TransferDirection", "AppEng.GuiITooltip.TransferToNetwork" ); + + registerApp( 48, Settings.SORT_DIRECTION, SortDir.ASCENDING, "AppEng.GuiITooltip.SortOrder", "AppEng.GuiITooltip.ToggleSortDirection" ); + registerApp( 49, Settings.SORT_DIRECTION, SortDir.DESCENDING, "AppEng.GuiITooltip.SortOrder", "AppEng.GuiITooltip.ToggleSortDirection" ); + + registerApp( 16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, "AppEng.GuiITooltip.SearchMode", "AppEng.GuiITooltip.SearchMode_Auto" ); + registerApp( 16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, "AppEng.GuiITooltip.SearchMode", + "AppEng.GuiITooltip.SearchMode_Standard" ); + registerApp( 16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.NEI_AUTOSEARCH, "AppEng.GuiITooltip.SearchMode", + "AppEng.GuiITooltip.SearchMode_NEIAuto" ); + registerApp( 16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.NEI_MANUAL_SEARCH, "AppEng.GuiITooltip.SearchMode", + "AppEng.GuiITooltip.SearchMode_NEIStandard" ); + + registerApp( 64, Settings.SORT_BY, SortOrder.NAME, "AppEng.GuiITooltip.SortBy", "AppEng.GuiITooltip.ItemName" ); + registerApp( 65, Settings.SORT_BY, SortOrder.AMOUNT, "AppEng.GuiITooltip.SortBy", "AppEng.GuiITooltip.NumberOfItems" ); + // registerApp( 66, Settings.SORT_BY, SortOrder.PRIORITY, "AppEng.GuiITooltip.SortBy", + // "AppEng.GuiITooltip.PriorityCellOrder" ); + registerApp( 68, Settings.SORT_BY, SortOrder.MOD, "AppEng.GuiITooltip.SortBy", "AppEng.GuiITooltip.ItemID" ); + + registerApp( 66, Settings.ACTIONS, ActionItems.WRENCH, "AppEng.GuiITooltip.PartitionStorage", "AppEng.GuiITooltip.PartitionStorageHint" ); + registerApp( 6, Settings.ACTIONS, ActionItems.CLOSE, "AppEng.Gui.Clear", "AppEng.GuiITooltip.ClearCraftingGrid" ); + + registerApp( 16, Settings.VIEW_MODE, ViewItems.STORED, "AppEng.GuiITooltip.View", "AppEng.GuiITooltip.StoredItems" ); + registerApp( 18, Settings.VIEW_MODE, ViewItems.ALL, "AppEng.GuiITooltip.View", "AppEng.GuiITooltip.StoredCraftable" ); + registerApp( 19, Settings.VIEW_MODE, ViewItems.CRAFTABLE, "AppEng.GuiITooltip.View", "AppEng.GuiITooltip.Craftable" ); + + registerApp( 16 * 6 + 0, Settings.FUZZY_MODE, FuzzyMode.PERCENT_25, "AppEng.GuiITooltip.FuzzyMode", "AppEng.GuiITooltip.FuzzyMode.Percent_25" ); + registerApp( 16 * 6 + 1, Settings.FUZZY_MODE, FuzzyMode.PERCENT_50, "AppEng.GuiITooltip.FuzzyMode", "AppEng.GuiITooltip.FuzzyMode.Percent_50" ); + registerApp( 16 * 6 + 2, Settings.FUZZY_MODE, FuzzyMode.PERCENT_75, "AppEng.GuiITooltip.FuzzyMode", "AppEng.GuiITooltip.FuzzyMode.Percent_75" ); + registerApp( 16 * 6 + 3, Settings.FUZZY_MODE, FuzzyMode.PERCENT_99, "AppEng.GuiITooltip.FuzzyMode", "AppEng.GuiITooltip.FuzzyMode.Percent_99" ); + registerApp( 16 * 6 + 4, Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL, "AppEng.GuiITooltip.FuzzyMode", "AppEng.GuiITooltip.FuzzyMode.IgnoreAll" ); + + registerApp( 80, Settings.FULLNESS_MODE, FullnessMode.EMPTY, "AppEng.GuiITooltip.OperationMode", "AppEng.GuiITooltip.MoveWhenEmpty" ); + registerApp( 81, Settings.FULLNESS_MODE, FullnessMode.HALF, "AppEng.GuiITooltip.OperationMode", "AppEng.GuiITooltip.MoveWhenWorkIsDone" ); + registerApp( 82, Settings.FULLNESS_MODE, FullnessMode.FULL, "AppEng.GuiITooltip.OperationMode", "AppEng.GuiITooltip.MoveWhenFull" ); + + registerApp( 16 * 8 + 0, Settings.TRASH_CATCH, YesNo.YES, "AppEng.GuiITooltip.TrashController", "AppEng.GuiITooltip.Disabled" ); + registerApp( 16 * 8 + 1, Settings.TRASH_CATCH, YesNo.NO, "AppEng.GuiITooltip.TrashController", "AppEng.GuiITooltip.Enable" ); + + registerApp( 16 * 1 + 5, Settings.BLOCK, YesNo.YES, "AppEng.GuiITooltip.InterfaceBlockingMode", "AppEng.GuiITooltip.Blocking" ); + registerApp( 16 * 1 + 4, Settings.BLOCK, YesNo.NO, "AppEng.GuiITooltip.InterfaceBlockingMode", "AppEng.GuiITooltip.NonBlocking" ); + + registerApp( 19, Settings.CRAFT, YesNo.YES, "AppEng.GuiITooltip.InterfaceCraftingMode", "AppEng.GuiITooltip.Craft" ); + registerApp( 17, Settings.CRAFT, YesNo.NO, "AppEng.GuiITooltip.InterfaceCraftingMode", "AppEng.GuiITooltip.DontCraft" ); + } + } + + @Override + public void drawButton(Minecraft par1Minecraft, int par2, int par3) + { + if ( this.drawButton ) + { + int iconIndex = getIconIndex(); + + if ( halfSize ) + { + width = 8; + height = 8; + + GL11.glPushMatrix(); + GL11.glTranslatef( this.xPosition, this.yPosition, 0.0F ); + GL11.glScalef( 0.5f, 0.5f, 0.5f ); + + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + par1Minecraft.renderEngine.bindTexture( ExtraTextures.GuiTexture( "guis/states.png" ) ); + this.field_82253_i = par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width + && par3 < this.yPosition + this.height; + + int uv_y = (int) Math.floor( iconIndex / 16 ); + int uv_x = iconIndex - uv_y * 16; + + this.drawTexturedModalRect( 0, 0, 256 - 16, 256 - 16, 16, 16 ); + this.drawTexturedModalRect( 0, 0, uv_x * 16, uv_y * 16, 16, 16 ); + this.mouseDragged( par1Minecraft, par2, par3 ); + + GL11.glPopMatrix(); + } + else + { + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + par1Minecraft.renderEngine.bindTexture( ExtraTextures.GuiTexture( "guis/states.png" ) ); + this.field_82253_i = par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width + && par3 < this.yPosition + this.height; + + int uv_y = (int) Math.floor( iconIndex / 16 ); + int uv_x = iconIndex - uv_y * 16; + + this.drawTexturedModalRect( this.xPosition, this.yPosition, 256 - 16, 256 - 16, 16, 16 ); + this.drawTexturedModalRect( this.xPosition, this.yPosition, uv_x * 16, uv_y * 16, 16, 16 ); + this.mouseDragged( par1Minecraft, par2, par3 ); + } + } + } + + private int getIconIndex() + { + if ( buttonSetting != null && currentValue != null ) + { + return Appearances.get( new EnumPair( buttonSetting, currentValue ) ).index; + } + return 256 - 1; + } + + public Enum getSetting() + { + return buttonSetting; + } + + public Enum getCurrentValue() + { + return currentValue; + } + + @Override + public String getMsg() + { + String DisplayName = null; + String DisplayValue = null; + + if ( buttonSetting != null && currentValue != null ) + { + BtnAppearance ba = Appearances.get( new EnumPair( buttonSetting, currentValue ) ); + DisplayName = ba.DisplayName; + DisplayValue = ba.DisplayValue; + } + + if ( DisplayName != null ) + { + String Name = StatCollector.translateToLocal( DisplayName ); + String Value = StatCollector.translateToLocal( DisplayValue ); + + if ( Name == null || Name.equals( "" ) ) + Name = DisplayName; + if ( Value == null || Value.equals( "" ) ) + Value = DisplayValue; + + if ( FillVar != null ) + Value = Value.replaceFirst( "%s", FillVar ); + + StringBuilder sb = new StringBuilder( Value ); + + int i = sb.lastIndexOf( "\n" ); + if ( i <= 0 ) + i = 0; + while (i + 30 < sb.length() && (i = sb.lastIndexOf( " ", i + 30 )) != -1) + { + sb.replace( i, i + 1, "\n" ); + } + + return Name + "\n" + sb.toString(); + } + return null; + } + + @Override + public int xPos() + { + return xPosition; + } + + @Override + public int yPos() + { + return yPosition; + } + + @Override + public int getWidth() + { + return halfSize ? 8 : 16; + } + + @Override + public int getHeight() + { + return halfSize ? 8 : 16; + } + + public void set(Enum e) + { + if ( currentValue != e ) + { + currentValue = e; + } + } + +} diff --git a/client/gui/widgets/GuiProgressBar.java b/client/gui/widgets/GuiProgressBar.java new file mode 100644 index 00000000..18ea2916 --- /dev/null +++ b/client/gui/widgets/GuiProgressBar.java @@ -0,0 +1,96 @@ +package appeng.client.gui.widgets; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.util.ResourceLocation; +import appeng.core.localization.GuiText; + +public class GuiProgressBar extends GuiButton implements ITooltip +{ + + public enum Direction + { + HORIZONTAL, VERTICAL + }; + + private ResourceLocation texture; + private int fill_u; + private int fill_v; + private int width; + private int height; + private Direction layout; + + public String FullMsg; + + public String TitleName; + public int current; + public int max; + + public GuiProgressBar(String string, int posX, int posY, int u, int y, int _width, int _height, Direction dir) { + super( posX, posY, _width, "" ); + texture = new ResourceLocation( "appliedenergistics2", "textures/" + string ); + width = _width; + height = _height; + fill_u = u; + fill_v = y; + current = 0; + max = 100; + layout = dir; + } + + @Override + public void drawButton(Minecraft par1Minecraft, int par2, int par3) + { + if ( this.drawButton ) + { + par1Minecraft.getTextureManager().bindTexture( texture ); + + if ( layout == Direction.VERTICAL ) + { + int diff = height - (max > 0 ? (height * current) / max : 0); + this.drawTexturedModalRect( this.xPosition, this.yPosition + diff, fill_u, fill_v + diff, width, height - diff ); + } + else + { + int diff = width - (max > 0 ? (width * current) / max : 0); + this.drawTexturedModalRect( this.xPosition, this.yPosition, fill_u + diff, fill_v, width - diff, height ); + } + + this.mouseDragged( par1Minecraft, par2, par3 ); + } + } + + @Override + public String getMsg() + { + if ( FullMsg != null ) + return FullMsg; + + return (TitleName != null ? TitleName : "") + "\n" + current + " " + GuiText.Of.getLocal() + " " + max; + } + + @Override + public int xPos() + { + return xPosition - 2; + } + + @Override + public int yPos() + { + return yPosition - 2; + } + + @Override + public int getWidth() + { + return width + 4; + } + + @Override + public int getHeight() + { + return height + 4; + } + +} diff --git a/client/gui/widgets/GuiScrollbar.java b/client/gui/widgets/GuiScrollbar.java new file mode 100644 index 00000000..88c964ac --- /dev/null +++ b/client/gui/widgets/GuiScrollbar.java @@ -0,0 +1,132 @@ +package appeng.client.gui.widgets; + +import org.lwjgl.opengl.GL11; + +import appeng.client.gui.AEBaseGui; + +public class GuiScrollbar implements IScrollSource +{ + + private int displayX = 0; + private int displayY = 0; + private int width = 12; + private int height = 16; + private int pageSize = 1; + + private int maxScroll = 0; + private int minScroll = 0; + private int currentScroll = 0; + + private void applyRange() + { + currentScroll = Math.max( Math.min( currentScroll, maxScroll ), minScroll ); + } + + public void draw(AEBaseGui g) + { + g.bindTexture( "minecraft", "gui/container/creative_inventory/tabs.png" ); + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + + if ( getRange() == 0 ) + { + g.drawTexturedModalRect( displayX, displayY, 232 + width, 0, width, 15 ); + } + else + { + int offset = (currentScroll - minScroll) * (height - 15) / getRange(); + g.drawTexturedModalRect( displayX, offset + displayY, 232, 0, width, 15 ); + } + } + + public int getRange() + { + return maxScroll - minScroll; + } + + public int getLeft() + { + return displayX; + } + + public int getTop() + { + return displayY; + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public GuiScrollbar setLeft(int v) + { + displayX = v; + return this; + } + + public GuiScrollbar setTop(int v) + { + displayY = v; + return this; + } + + public GuiScrollbar setWidth(int v) + { + width = v; + return this; + } + + public GuiScrollbar setHeight(int v) + { + height = v; + return this; + } + + public void setRange(int min, int max, int pageSize) + { + minScroll = min; + maxScroll = max; + this.pageSize = pageSize; + + if ( minScroll > maxScroll ) + maxScroll = minScroll; + + applyRange(); + } + + @Override + public int getCurrentScroll() + { + return currentScroll; + } + + public void click(AEBaseGui aeBaseGui, int x, int y) + { + if ( getRange() == 0 ) + return; + + if ( x > displayX && x <= displayX + width ) + { + if ( y > displayY && y <= displayY + height ) + { + currentScroll = (y - displayY); + currentScroll = minScroll + ((currentScroll * 2 * getRange() / height)); + currentScroll = (currentScroll + 1) >> 1; + applyRange(); + } + } + } + + public void wheel(int delta) + { + delta = Math.max( Math.min( -delta, 1 ), -1 ); + currentScroll += delta * pageSize; + applyRange(); + } + +} diff --git a/client/gui/widgets/IScrollSource.java b/client/gui/widgets/IScrollSource.java new file mode 100644 index 00000000..928cbe2e --- /dev/null +++ b/client/gui/widgets/IScrollSource.java @@ -0,0 +1,8 @@ +package appeng.client.gui.widgets; + +public interface IScrollSource +{ + + int getCurrentScroll(); + +} diff --git a/client/gui/widgets/ITooltip.java b/client/gui/widgets/ITooltip.java new file mode 100644 index 00000000..c5a1c0d4 --- /dev/null +++ b/client/gui/widgets/ITooltip.java @@ -0,0 +1,45 @@ +package appeng.client.gui.widgets; + +/** + * AEBaseGui controlled Tooltip Interface. + * + */ +public interface ITooltip +{ + + /** + * returns the tooltip message. + * + * @return + */ + String getMsg(); + + /** + * x Location for the object that triggers the tooltip. + * + * @return xPosition + */ + int xPos(); + + /** + * y Location for the object that triggers the tooltip. + * + * @return yPosition + */ + int yPos(); + + /** + * Width of the object that triggers the tooltip. + * + * @return width + */ + int getWidth(); + + /** + * Height for the object that triggers the tooltip. + * + * @return height + */ + int getHeight(); + +} diff --git a/client/me/InternalSlotME.java b/client/me/InternalSlotME.java new file mode 100644 index 00000000..ac79879c --- /dev/null +++ b/client/me/InternalSlotME.java @@ -0,0 +1,31 @@ +package appeng.client.me; + +import net.minecraft.item.ItemStack; +import appeng.api.storage.data.IAEItemStack; + +public class InternalSlotME +{ + + private final ItemRepo repo; + + public int offset; + public int xPos; + public int yPos; + + public InternalSlotME(ItemRepo def, int offset, int displayX, int displayY) { + this.repo = def; + this.offset = offset; + this.xPos = displayX; + this.yPos = displayY; + } + + public ItemStack getStack() + { + return repo.getItem( offset ); + } + + public IAEItemStack getAEStack() + { + return repo.getRefrenceItem( offset ); + } +} diff --git a/client/me/ItemRepo.java b/client/me/ItemRepo.java new file mode 100644 index 00000000..6212a8b6 --- /dev/null +++ b/client/me/ItemRepo.java @@ -0,0 +1,148 @@ +package appeng.client.me; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Pattern; + +import net.minecraft.item.ItemStack; +import appeng.api.config.Settings; +import appeng.api.config.SortOrder; +import appeng.api.config.YesNo; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.client.gui.widgets.IScrollSource; +import appeng.core.Configuration; +import appeng.util.ItemSorters; +import appeng.util.Platform; +import appeng.util.item.ItemList; + +public class ItemRepo +{ + + final private IItemList list = new ItemList(); + final private ArrayList view = new ArrayList(); + final private ArrayList dsp = new ArrayList(); + final private IScrollSource src; + + public int rowSize = 9; + + public String searchString = ""; + + public ItemRepo(IScrollSource src) { + this.src = src; + } + + public IAEItemStack getRefrenceItem(int idx) + { + idx += src.getCurrentScroll() * rowSize; + + if ( idx >= view.size() ) + return null; + return view.get( idx ); + } + + public ItemStack getItem(int idx) + { + idx += src.getCurrentScroll() * rowSize; + + if ( idx >= dsp.size() ) + return null; + return dsp.get( idx ); + } + + void setSearch(String search) + { + searchString = search == null ? "" : search; + } + + public void postUpdate(IAEItemStack is) + { + IAEItemStack st = list.findPrecise( is ); + + if ( st != null ) + { + st.reset(); + st.add( is ); + } + else + list.add( is ); + } + + public void updateView() + { + view.clear(); + dsp.clear(); + + view.ensureCapacity( list.size() ); + dsp.ensureCapacity( list.size() ); + + boolean terminalSearchToolTips = Configuration.instance.settings.getSetting( Settings.SEARCH_TOOLTIPS ) != YesNo.NO; + // boolean terminalSearchMods = Configuration.instance.settings.getSetting( Settings.SEARCH_MODS ) != YesNo.NO; + + Pattern m = null; + try + { + m = Pattern.compile( searchString.toLowerCase(), Pattern.CASE_INSENSITIVE ); + } + catch (Throwable _) + { + try + { + m = Pattern.compile( Pattern.quote( searchString.toLowerCase() ), Pattern.CASE_INSENSITIVE ); + } + catch (Throwable __) + { + return; + } + } + + boolean notDone = false; + for (IAEItemStack is : list) + { + String dspName = Platform.getItemDisplayName( is ); + notDone = true; + + if ( m.matcher( dspName.toLowerCase() ).find() ) + { + view.add( is ); + notDone = false; + } + + if ( terminalSearchToolTips && notDone ) + { + for (Object lp : Platform.getTooltip( is )) + if ( lp instanceof String && m.matcher( (String) lp ).find() ) + { + view.add( is ); + notDone = false; + break; + } + } + + /* + * if ( terminalSearchMods && notDone ) { if ( m.matcher( Platform.getMod( is.getItemStack() ) ).find() ) { + * view.add( is ); notDone = false; } } + */ + } + + Enum SortBy = Configuration.instance.settings.getSetting( Settings.SORT_BY ); + Enum SortDir = Configuration.instance.settings.getSetting( Settings.SORT_DIRECTION ); + + ItemSorters.Direction = (appeng.api.config.SortDir) SortDir; + + if ( SortBy == SortOrder.AMOUNT ) + Collections.sort( view, ItemSorters.ConfigBased_SortBySize ); + else if ( SortBy == SortOrder.MOD ) + Collections.sort( view, ItemSorters.ConfigBased_SortByMod ); + else + Collections.sort( view, ItemSorters.ConfigBased_SortByName ); + + for (IAEItemStack is : view) + dsp.add( is.getItemStack() ); + } + + public int size() + { + return view.size(); + } +} diff --git a/client/me/SlotME.java b/client/me/SlotME.java new file mode 100644 index 00000000..180ca510 --- /dev/null +++ b/client/me/SlotME.java @@ -0,0 +1,77 @@ +package appeng.client.me; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import appeng.api.storage.data.IAEItemStack; + +public class SlotME extends Slot +{ + + public InternalSlotME mySlot; + + public SlotME(InternalSlotME me) { + super( null, 0, me.xPos, me.yPos ); + mySlot = me; + } + + @Override + public ItemStack getStack() + { + return mySlot.getStack(); + } + + public IAEItemStack getAEStack() + { + return mySlot.getAEStack(); + } + + @Override + public boolean canTakeStack(EntityPlayer par1EntityPlayer) + { + return false; + } + + @Override + public ItemStack decrStackSize(int par1) + { + return null; + } + + @Override + public void putStack(ItemStack par1ItemStack) + { + + } + + @Override + public boolean getHasStack() + { + return getStack() != null; + } + + @Override + public boolean isItemValid(ItemStack par1ItemStack) + { + return false; + } + + @Override + public int getSlotStackLimit() + { + return 0; + } + + @Override + public boolean isSlotInInventory(IInventory par1iInventory, int par2) + { + return false; + } + + @Override + public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) + { + } + +} diff --git a/client/render/AppEngRenderItem.java b/client/render/AppEngRenderItem.java new file mode 100644 index 00000000..528e3d71 --- /dev/null +++ b/client/render/AppEngRenderItem.java @@ -0,0 +1,143 @@ +package appeng.client.render; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.item.ItemStack; + +import org.lwjgl.opengl.GL11; + +import appeng.api.storage.data.IAEItemStack; +import appeng.core.Configuration; + +public class AppEngRenderItem extends RenderItem +{ + + public IAEItemStack aestack; + + private void renderQuad(Tessellator par1Tessellator, int par2, int par3, int par4, int par5, int par6) + { + par1Tessellator.startDrawingQuads(); + par1Tessellator.setColorOpaque_I( par6 ); + par1Tessellator.addVertex( par2 + 0, par3 + 0, 0.0D ); + par1Tessellator.addVertex( par2 + 0, par3 + par5, 0.0D ); + par1Tessellator.addVertex( par2 + par4, par3 + par5, 0.0D ); + par1Tessellator.addVertex( par2 + par4, par3 + 0, 0.0D ); + par1Tessellator.draw(); + } + + @Override + public void renderItemOverlayIntoGUI(FontRenderer par1FontRenderer, TextureManager par2RenderEngine, ItemStack par3ItemStack, int par4, int par5) + { + this.renderItemOverlayIntoGUI( par1FontRenderer, par2RenderEngine, par3ItemStack, par4, par5, (String) null ); + } + + @Override + public void renderItemOverlayIntoGUI(FontRenderer par1FontRenderer, TextureManager par2RenderEngine, ItemStack is, int par4, int par5, String par6Str) + { + if ( is != null ) + { + float ScaleFactor = Configuration.instance.useTerminalUseLargeFont() ? 0.85f : 0.5f; + float RScaleFactor = 1.0f / ScaleFactor; + int offset = Configuration.instance.useTerminalUseLargeFont() ? 0 : -1; + + if ( is.isItemDamaged() ) + { + int k = (int) Math.round( 13.0D - is.getItemDamageForDisplay() * 13.0D / is.getMaxDamage() ); + int l = (int) Math.round( 255.0D - is.getItemDamageForDisplay() * 255.0D / is.getMaxDamage() ); + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL11.GL_DEPTH_TEST ); + GL11.glDisable( GL11.GL_TEXTURE_2D ); + Tessellator tessellator = Tessellator.instance; + int i1 = 255 - l << 16 | l << 8; + int j1 = (255 - l) / 4 << 16 | 16128; + this.renderQuad( tessellator, par4 + 2, par5 + 13, 13, 2, 0 ); + this.renderQuad( tessellator, par4 + 2, par5 + 13, 12, 1, j1 ); + this.renderQuad( tessellator, par4 + 2, par5 + 13, k, 1, i1 ); + GL11.glEnable( GL11.GL_TEXTURE_2D ); + GL11.glEnable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_DEPTH_TEST ); + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + } + + if ( is.stackSize == 0 ) + { + String var6 = Configuration.instance.useTerminalUseLargeFont() ? "+" : "Craft"; + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL11.GL_DEPTH_TEST ); + GL11.glPushMatrix(); + GL11.glScaled( ScaleFactor, ScaleFactor, ScaleFactor ); + int X = (int) (((float) par4 + offset + 16.0f - par1FontRenderer.getStringWidth( var6 ) * ScaleFactor) * RScaleFactor); + int Y = (int) (((float) par5 + offset + 16.0f - 7.0f * ScaleFactor) * RScaleFactor); + par1FontRenderer.drawStringWithShadow( var6, X, Y, 16777215 ); + GL11.glPopMatrix(); + GL11.glEnable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_DEPTH_TEST ); + } + + long amount = aestack != null ? aestack.getStackSize() : is.stackSize; + if ( amount > 999999999999L ) + amount = 999999999999L; + + if ( amount != 0 ) + { + String var6 = "" + Math.abs( amount ); + + if ( Configuration.instance.useTerminalUseLargeFont() ) + { + if ( amount > 999999999 ) + { + var6 = "" + (int) Math.floor( amount / 1000000000.0 ) + "B"; + } + else if ( amount > 99999999 ) + { + var6 = "." + (int) Math.floor( amount / 100000000.0 ) + "B"; + } + else if ( amount > 999999 ) + { + var6 = "" + (int) Math.floor( amount / 1000000.0 ) + "M"; + } + else if ( amount > 99999 ) + { + var6 = "." + (int) Math.floor( amount / 100000.0 ) + "M"; + } + else if ( amount > 999 ) + { + var6 = "" + (int) Math.floor( amount / 1000.0 ) + "K"; + } + } + else + { + if ( amount > 999999999 ) + { + var6 = "" + (int) Math.floor( amount / 1000000000.0 ) + "B"; + } + else if ( amount > 999999999 ) + { + var6 = "" + (int) Math.floor( amount / 1000000000.0 ) + "B"; + } + else if ( amount > 999999 ) + { + var6 = "" + (int) Math.floor( amount / 1000000.0 ) + "M"; + } + else if ( amount > 9999 ) + { + var6 = "" + (int) Math.floor( amount / 1000.0 ) + "K"; + } + } + + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL11.GL_DEPTH_TEST ); + GL11.glPushMatrix(); + GL11.glScaled( ScaleFactor, ScaleFactor, ScaleFactor ); + int X = (int) (((float) par4 + offset + 16.0f - par1FontRenderer.getStringWidth( var6 ) * ScaleFactor) * RScaleFactor); + int Y = (int) (((float) par5 + offset + 16.0f - 7.0f * ScaleFactor) * RScaleFactor); + par1FontRenderer.drawStringWithShadow( var6, X, Y, 16777215 ); + GL11.glPopMatrix(); + GL11.glEnable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_DEPTH_TEST ); + } + } + } +} diff --git a/client/render/BaseBlockRender.java b/client/render/BaseBlockRender.java new file mode 100644 index 00000000..86eb8f36 --- /dev/null +++ b/client/render/BaseBlockRender.java @@ -0,0 +1,750 @@ +package appeng.client.render; + +import java.nio.FloatBuffer; +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; + +import appeng.api.util.IOrientable; +import appeng.api.util.IOrientableBlock; +import appeng.block.AEBaseBlock; +import appeng.client.texture.ExtraTextures; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class BaseBlockRender +{ + + final int ORIENTATION_BITS = 7; + final static int FLIP_H_BIT = 8; + final static int FLIP_V_BIT = 16; + + final double MAX_DISTANCE; + final public boolean hasTESR; + final static private byte OrientationMap[][][] = new byte[6][6][6]; + + static public int getOrientation(ForgeDirection in, ForgeDirection forward, ForgeDirection up) + { + if ( in == null || in.equals( ForgeDirection.UNKNOWN ) // 1 + || forward == null || forward.equals( ForgeDirection.UNKNOWN ) // 2 + || up == null || up.equals( ForgeDirection.UNKNOWN ) ) + return 0; + + int a = in.ordinal(); + int b = forward.ordinal(); + int c = up.ordinal(); + + return OrientationMap[a][b][c]; + } + + static public void setOriMap() + { + // pointed up... + OrientationMap[0][3][1] = 0; + OrientationMap[1][3][1] = 0; + OrientationMap[2][3][1] = 0; + OrientationMap[3][3][1] = 0; + OrientationMap[4][3][1] = 0; + OrientationMap[5][3][1] = 0; + + OrientationMap[0][5][1] = 1; + OrientationMap[1][5][1] = 2; + OrientationMap[2][5][1] = 0; + OrientationMap[3][5][1] = 0; + OrientationMap[4][5][1] = 0; + OrientationMap[5][5][1] = 0; + + OrientationMap[0][2][1] = 3; + OrientationMap[1][2][1] = 3; + OrientationMap[2][2][1] = 0; + OrientationMap[3][2][1] = 0; + OrientationMap[4][2][1] = 0; + OrientationMap[5][2][1] = 0; + + OrientationMap[0][4][1] = 2; + OrientationMap[1][4][1] = 1; + OrientationMap[2][4][1] = 0; + OrientationMap[3][4][1] = 0; + OrientationMap[4][4][1] = 0; + OrientationMap[5][4][1] = 0; + + // upside down + OrientationMap[0][3][0] = 0 | FLIP_H_BIT; + OrientationMap[1][3][0] = 0 | FLIP_H_BIT; + OrientationMap[2][3][0] = 3; + OrientationMap[3][3][0] = 3; + OrientationMap[4][3][0] = 3; + OrientationMap[5][3][0] = 3; + + OrientationMap[0][4][0] = 2 | FLIP_H_BIT; + OrientationMap[1][4][0] = 1 | FLIP_H_BIT; + OrientationMap[2][4][0] = 3; + OrientationMap[3][4][0] = 3; + OrientationMap[4][4][0] = 3; + OrientationMap[5][4][0] = 3; + + OrientationMap[0][5][0] = 1 | FLIP_H_BIT; + OrientationMap[1][5][0] = 2 | FLIP_H_BIT; + OrientationMap[2][5][0] = 3; + OrientationMap[3][5][0] = 3; + OrientationMap[4][5][0] = 3; + OrientationMap[5][5][0] = 3; + + OrientationMap[0][2][0] = 3 | FLIP_H_BIT; + OrientationMap[1][2][0] = 3 | FLIP_H_BIT; + OrientationMap[2][2][0] = 3; + OrientationMap[3][2][0] = 3; + OrientationMap[4][2][0] = 3; + OrientationMap[5][2][0] = 3; + + // side 1 + OrientationMap[0][3][5] = 1 | FLIP_V_BIT; + OrientationMap[1][3][5] = 1 | FLIP_H_BIT; + OrientationMap[2][3][5] = 1; + OrientationMap[3][3][5] = 1; + OrientationMap[4][3][5] = 1; + OrientationMap[5][3][5] = 1 | FLIP_V_BIT; + + OrientationMap[0][1][5] = 1 | FLIP_H_BIT; + OrientationMap[1][1][5] = 1; + OrientationMap[2][1][5] = 3 | FLIP_V_BIT; + OrientationMap[3][1][5] = 3; + OrientationMap[4][1][5] = 1 | FLIP_V_BIT; + OrientationMap[5][1][5] = 1; + + OrientationMap[0][2][5] = 1 | FLIP_H_BIT; + OrientationMap[1][2][5] = 1 | FLIP_H_BIT; + OrientationMap[2][2][5] = 1; + OrientationMap[3][2][5] = 2 | FLIP_V_BIT; + OrientationMap[4][2][5] = 1 | FLIP_V_BIT; + OrientationMap[5][2][5] = 1; + + OrientationMap[0][0][5] = 1 | FLIP_H_BIT; + OrientationMap[1][0][5] = 1; + OrientationMap[2][0][5] = 0; + OrientationMap[3][0][5] = 0 | FLIP_V_BIT; + OrientationMap[4][0][5] = 1; + OrientationMap[5][0][5] = 1 | FLIP_V_BIT; + + // side 2 + OrientationMap[0][1][2] = 0 | FLIP_H_BIT; + OrientationMap[1][1][2] = 0; + OrientationMap[2][1][2] = 2 | FLIP_H_BIT; + OrientationMap[3][1][2] = 1; + OrientationMap[4][1][2] = 3; + OrientationMap[5][1][2] = 3 | FLIP_H_BIT; + + OrientationMap[0][4][2] = 0 | FLIP_H_BIT; + OrientationMap[1][4][2] = 0 | FLIP_H_BIT; + OrientationMap[2][4][2] = 2 | FLIP_H_BIT; + OrientationMap[3][4][2] = 1; + OrientationMap[4][4][2] = 1 | FLIP_H_BIT; + OrientationMap[5][4][2] = 2; + + OrientationMap[0][0][2] = 0 | FLIP_V_BIT; + OrientationMap[1][0][2] = 0; + OrientationMap[2][0][2] = 2; + OrientationMap[3][0][2] = 1 | FLIP_H_BIT; + OrientationMap[4][0][2] = 3 | FLIP_H_BIT; + OrientationMap[5][0][2] = 0; + + OrientationMap[0][5][2] = 0 | FLIP_H_BIT; + OrientationMap[1][5][2] = 0 | FLIP_H_BIT; + OrientationMap[2][5][2] = 2; + OrientationMap[3][5][2] = 1 | FLIP_H_BIT; + OrientationMap[4][5][2] = 2; + OrientationMap[5][5][2] = 1 | FLIP_H_BIT; + + // side 3 + OrientationMap[0][0][3] = 3 | FLIP_H_BIT; + OrientationMap[1][0][3] = 3; + OrientationMap[2][0][3] = 1; + OrientationMap[3][0][3] = 2 | FLIP_H_BIT; + OrientationMap[4][0][3] = 0; + OrientationMap[5][0][3] = 0 | FLIP_H_BIT; + + OrientationMap[0][4][3] = 3; + OrientationMap[1][4][3] = 3; + OrientationMap[2][4][3] = 1 | FLIP_H_BIT; + OrientationMap[3][4][3] = 2; + OrientationMap[4][4][3] = 1; + OrientationMap[5][4][3] = 2 | FLIP_H_BIT; + + OrientationMap[0][1][3] = 3 | FLIP_V_BIT; + OrientationMap[1][1][3] = 3; + OrientationMap[2][1][3] = 1 | FLIP_H_BIT; + OrientationMap[3][1][3] = 2; + OrientationMap[4][1][3] = 3 | FLIP_H_BIT; + OrientationMap[5][1][3] = 0; + + OrientationMap[0][5][3] = 3; + OrientationMap[1][5][3] = 3; + OrientationMap[2][5][3] = 1; + OrientationMap[3][5][3] = 2 | FLIP_H_BIT; + OrientationMap[4][5][3] = 2 | FLIP_H_BIT; + OrientationMap[5][5][3] = 1; + + // side 4 + OrientationMap[0][3][4] = 1; + OrientationMap[1][3][4] = 2; + OrientationMap[2][3][4] = 2 | FLIP_H_BIT; + OrientationMap[3][3][4] = 1; + OrientationMap[4][3][4] = 2 | FLIP_H_BIT; + OrientationMap[5][3][4] = 1; + + OrientationMap[0][0][4] = 1 | FLIP_H_BIT; + OrientationMap[1][0][4] = 2; + OrientationMap[2][0][4] = 0; + OrientationMap[3][0][4] = 0 | FLIP_H_BIT; + OrientationMap[4][0][4] = 2 | FLIP_H_BIT; + OrientationMap[5][0][4] = 1; + + OrientationMap[0][1][4] = 1 | FLIP_H_BIT; + OrientationMap[1][1][4] = 2; + OrientationMap[2][1][4] = 3 | FLIP_H_BIT; + OrientationMap[3][1][4] = 3; + OrientationMap[4][1][4] = 2; + OrientationMap[5][1][4] = 1 | FLIP_H_BIT; + + OrientationMap[0][2][4] = 1; + OrientationMap[1][2][4] = 2; + OrientationMap[2][2][4] = 1; + OrientationMap[3][2][4] = 2 | FLIP_H_BIT; + OrientationMap[4][2][4] = 2; + OrientationMap[5][2][4] = 1 | FLIP_H_BIT; + } + + public BaseBlockRender() { + this( false, 20 ); + } + + public BaseBlockRender(boolean enableTESR, double TESRrange) { + hasTESR = enableTESR; + MAX_DISTANCE = TESRrange; + setOriMap(); + } + + public double getTesrRenderDistance() + { + return MAX_DISTANCE; + } + + public Icon firstNotNull(Icon... s) + { + for (Icon o : s) + if ( o != null ) + return o; + return ExtraTextures.getMissing(); + } + + public void renderInvBlock(EnumSet sides, AEBaseBlock block, Tessellator tess, int color, RenderBlocks renderer) + { + if ( tess.isDrawing ) + tess.draw(); + + if ( sides.contains( ForgeDirection.DOWN ) ) + { + tess.startDrawingQuads(); + tess.setNormal( 0.0F, -1.0F, 0.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceYNeg( block, 0.0D, 0.0D, 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.DOWN ), block.getIcon( 0, 0 ) ) ); + tess.draw(); + } + + if ( sides.contains( ForgeDirection.UP ) ) + { + tess.startDrawingQuads(); + tess.setNormal( 0.0F, 1.0F, 0.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceYPos( + block, + 0.0D, + 0.0D, + 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.UP ), + block.getIcon( ForgeDirection.UP.ordinal(), 0 ) ) ); + tess.draw(); + } + + if ( sides.contains( ForgeDirection.NORTH ) ) + { + tess.startDrawingQuads(); + tess.setNormal( 0.0F, 0.0F, -1.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceZNeg( + block, + 0.0D, + 0.0D, + 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.NORTH ), + block.getIcon( ForgeDirection.NORTH.ordinal(), 0 ) ) ); + tess.draw(); + } + + if ( sides.contains( ForgeDirection.SOUTH ) ) + { + tess.startDrawingQuads(); + tess.setNormal( 0.0F, 0.0F, 1.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceZPos( + block, + 0.0D, + 0.0D, + 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.SOUTH ), + block.getIcon( ForgeDirection.SOUTH.ordinal(), 0 ) ) ); + tess.draw(); + } + + if ( sides.contains( ForgeDirection.WEST ) ) + { + tess.startDrawingQuads(); + tess.setNormal( -1.0F, 0.0F, 0.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceXNeg( + block, + 0.0D, + 0.0D, + 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.WEST ), + block.getIcon( ForgeDirection.WEST.ordinal(), 0 ) ) ); + tess.draw(); + } + + if ( sides.contains( ForgeDirection.EAST ) ) + { + tess.startDrawingQuads(); + tess.setNormal( 1.0F, 0.0F, 0.0F ); + tess.setColorOpaque_I( color ); + renderer.renderFaceXPos( + block, + 0.0D, + 0.0D, + 0.0D, + firstNotNull( renderer.overrideBlockTexture, block.getRendererInstance().getTexture( ForgeDirection.EAST ), + block.getIcon( ForgeDirection.EAST.ordinal(), 0 ) ) ); + tess.draw(); + } + } + + public void renderInventory(AEBaseBlock block, ItemStack item, RenderBlocks renderer) + { + Tessellator tess = Tessellator.instance; + + BlockRenderInfo info = block.getRendererInstance(); + if ( info.isValid() ) + { + renderer.uvRotateBottom = info.getTexture( ForgeDirection.DOWN ).setFlip( + getOrientation( ForgeDirection.DOWN, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + renderer.uvRotateTop = info.getTexture( ForgeDirection.UP ).setFlip( getOrientation( ForgeDirection.UP, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + + renderer.uvRotateEast = info.getTexture( ForgeDirection.EAST ).setFlip( + getOrientation( ForgeDirection.EAST, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + renderer.uvRotateWest = info.getTexture( ForgeDirection.WEST ).setFlip( + getOrientation( ForgeDirection.WEST, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + + renderer.uvRotateNorth = info.getTexture( ForgeDirection.NORTH ).setFlip( + getOrientation( ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + renderer.uvRotateSouth = info.getTexture( ForgeDirection.SOUTH ).setFlip( + getOrientation( ForgeDirection.SOUTH, ForgeDirection.SOUTH, ForgeDirection.UP ) ); + + } + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), block, tess, 0xffffff, renderer ); + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + } + + public IOrientable getOrientable(AEBaseBlock block, IBlockAccess w, int x, int y, int z) + { + if ( block.hasBlockTileEntity() ) + return (AEBaseTile) block.getTileEntity( w, x, y, z ); + else if ( block instanceof IOrientableBlock ) + return ((IOrientableBlock) block).getOrientable( w, x, y, z ); + return null; + } + + public void preRenderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + ForgeDirection forward = ForgeDirection.SOUTH; + ForgeDirection up = ForgeDirection.UP; + + BlockRenderInfo info = block.getRendererInstance(); + IOrientable te = getOrientable( block, world, x, y, z ); + if ( te != null ) + { + forward = te.getForward(); + up = te.getUp(); + + renderer.uvRotateBottom = info.getTexture( ForgeDirection.DOWN ).setFlip( getOrientation( ForgeDirection.DOWN, forward, up ) ); + renderer.uvRotateTop = info.getTexture( ForgeDirection.UP ).setFlip( getOrientation( ForgeDirection.UP, forward, up ) ); + + renderer.uvRotateEast = info.getTexture( ForgeDirection.EAST ).setFlip( getOrientation( ForgeDirection.EAST, forward, up ) ); + renderer.uvRotateWest = info.getTexture( ForgeDirection.WEST ).setFlip( getOrientation( ForgeDirection.WEST, forward, up ) ); + + renderer.uvRotateNorth = info.getTexture( ForgeDirection.NORTH ).setFlip( getOrientation( ForgeDirection.NORTH, forward, up ) ); + renderer.uvRotateSouth = info.getTexture( ForgeDirection.SOUTH ).setFlip( getOrientation( ForgeDirection.SOUTH, forward, up ) ); + } + + } + + public void postRenderInWorld(RenderBlocks renderer) + { + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + } + + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + preRenderInWorld( block, world, x, y, z, renderer ); + + boolean o = renderer.renderStandardBlock( block, x, y, z ); + + postRenderInWorld( renderer ); + return o; + } + + final FloatBuffer rotMat = BufferUtils.createFloatBuffer( 16 ); + + protected void applyTESRRotation(double x, double y, double z, ForgeDirection forward, ForgeDirection up) + { + if ( forward != null && up != null ) + { + ForgeDirection west = Platform.crossProduct( forward, up ); + + rotMat.put( 0, west.offsetX ); + rotMat.put( 1, west.offsetY ); + rotMat.put( 2, west.offsetZ ); + rotMat.put( 3, 0 ); + + rotMat.put( 4, up.offsetX ); + rotMat.put( 5, up.offsetY ); + rotMat.put( 6, up.offsetZ ); + rotMat.put( 7, 0 ); + + rotMat.put( 8, forward.offsetX ); + rotMat.put( 9, forward.offsetY ); + rotMat.put( 10, forward.offsetZ ); + rotMat.put( 11, 0 ); + + rotMat.put( 12, 0 ); + rotMat.put( 13, 0 ); + rotMat.put( 14, 0 ); + rotMat.put( 15, 1 ); + GL11.glTranslated( x + 0.5, y + 0.5, z + 0.5 ); + GL11.glMultMatrix( rotMat ); + GL11.glTranslated( -0.5, -0.5, -0.5 ); + GL11.glCullFace( GL11.GL_FRONT ); + } + else + { + GL11.glTranslated( x, y, z ); + } + } + + protected void setInvRenderBounds(RenderBlocks renderer, int i, int j, int k, int l, int m, int n) + { + renderer.setRenderBounds( i / 16.0, j / 16.0, k / 16.0, l / 16.0, m / 16.0, n / 16.0 ); + } + + protected void renderBlockBounds(RenderBlocks renderer, + + double minX, double minY, double minZ, + + double maxX, double maxY, double maxZ, + + ForgeDirection x, ForgeDirection y, ForgeDirection z) + { + minX /= 16.0; + minY /= 16.0; + minZ /= 16.0; + maxX /= 16.0; + maxY /= 16.0; + maxZ /= 16.0; + + double aX = minX * x.offsetX + minY * y.offsetX + minZ * z.offsetX; + double aY = minX * x.offsetY + minY * y.offsetY + minZ * z.offsetY; + double aZ = minX * x.offsetZ + minY * y.offsetZ + minZ * z.offsetZ; + + double bX = maxX * x.offsetX + maxY * y.offsetX + maxZ * z.offsetX; + double bY = maxX * x.offsetY + maxY * y.offsetY + maxZ * z.offsetY; + double bZ = maxX * x.offsetZ + maxY * y.offsetZ + maxZ * z.offsetZ; + + if ( x.offsetX + y.offsetX + z.offsetX < 0 ) + { + aX += 1; + bX += 1; + } + + if ( x.offsetY + y.offsetY + z.offsetY < 0 ) + { + aY += 1; + bY += 1; + } + + if ( x.offsetZ + y.offsetZ + z.offsetZ < 0 ) + { + aZ += 1; + bZ += 1; + } + + renderer.renderMinX = Math.min( aX, bX ); + renderer.renderMinY = Math.min( aY, bY ); + renderer.renderMinZ = Math.min( aZ, bZ ); + renderer.renderMaxX = Math.max( aX, bX ); + renderer.renderMaxY = Math.max( aY, bY ); + renderer.renderMaxZ = Math.max( aZ, bZ ); + } + + @SideOnly(Side.CLIENT) + private void renderFace(Tessellator tess, double offsetX, double offsetY, double offsetZ, double ax, double ay, double az, double bx, double by, double bz, + double ua, double ub, double va, double vb, Icon ico, boolean flip) + { + if ( flip ) + { + tess.addVertexWithUV( offsetX + ax * ua + bx * va, offsetY + ay * ua + by * va, offsetZ + az * ua + bz * va, ico.getInterpolatedU( ua * 16.0 ), + ico.getInterpolatedV( va * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ua + bx * vb, offsetY + ay * ua + by * vb, offsetZ + az * ua + bz * vb, ico.getInterpolatedU( ua * 16.0 ), + ico.getInterpolatedV( vb * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ub + bx * vb, offsetY + ay * ub + by * vb, offsetZ + az * ub + bz * vb, ico.getInterpolatedU( ub * 16.0 ), + ico.getInterpolatedV( vb * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ub + bx * va, offsetY + ay * ub + by * va, offsetZ + az * ub + bz * va, ico.getInterpolatedU( ub * 16.0 ), + ico.getInterpolatedV( va * 16.0 ) ); + } + else + { + tess.addVertexWithUV( offsetX + ax * ua + bx * va, offsetY + ay * ua + by * va, offsetZ + az * ua + bz * va, ico.getInterpolatedU( ua * 16.0 ), + ico.getInterpolatedV( va * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ub + bx * va, offsetY + ay * ub + by * va, offsetZ + az * ub + bz * va, ico.getInterpolatedU( ub * 16.0 ), + ico.getInterpolatedV( va * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ub + bx * vb, offsetY + ay * ub + by * vb, offsetZ + az * ub + bz * vb, ico.getInterpolatedU( ub * 16.0 ), + ico.getInterpolatedV( vb * 16.0 ) ); + tess.addVertexWithUV( offsetX + ax * ua + bx * vb, offsetY + ay * ua + by * vb, offsetZ + az * ua + bz * vb, ico.getInterpolatedU( ua * 16.0 ), + ico.getInterpolatedV( vb * 16.0 ) ); + } + } + + @SideOnly(Side.CLIENT) + protected void renderCutoutFace(Block block, Icon ico, int x, int y, int z, RenderBlocks renderer, ForgeDirection orientation, float edgeThickness) + { + Tessellator tess = Tessellator.instance; + + double offsetX = 0.0, offsetY = 0.0, offsetZ = 0.0; + double layaX = 0.0, layaY = 0.0, layaZ = 0.0; + double laybX = 0.0, laybY = 0.0, laybZ = 0.0; + + boolean flip = false; + switch (orientation) + { + case NORTH: + + layaX = 1.0; + laybY = 1.0; + flip = true; + + break; + case SOUTH: + + layaX = 1.0; + laybY = 1.0; + offsetZ = 1.0; + + break; + case EAST: + + flip = true; + layaZ = 1.0; + laybY = 1.0; + offsetX = 1.0; + + break; + case WEST: + + layaZ = 1.0; + laybY = 1.0; + + break; + case UP: + + flip = true; + layaX = 1.0; + laybZ = 1.0; + offsetY = 1.0; + + break; + case DOWN: + + layaX = 1.0; + laybZ = 1.0; + + break; + default: + break; + } + + offsetX += x; + offsetY += y; + offsetZ += z; + + renderFace( tess, offsetX, offsetY, offsetZ, layaX, layaY, layaZ, laybX, laybY, laybZ, + // u -> u + 0, 1.0, + // v -> v + 0, edgeThickness, ico, flip ); + + renderFace( tess, offsetX, offsetY, offsetZ, layaX, layaY, layaZ, laybX, laybY, laybZ, + // u -> u + 0.0, edgeThickness, + // v -> v + edgeThickness, 1.0 - edgeThickness, ico, flip ); + + renderFace( tess, offsetX, offsetY, offsetZ, layaX, layaY, layaZ, laybX, laybY, laybZ, + // u -> u + 1.0 - edgeThickness, 1.0, + // v -> v + edgeThickness, 1.0 - edgeThickness, ico, flip ); + + renderFace( tess, offsetX, offsetY, offsetZ, layaX, layaY, layaZ, laybX, laybY, laybZ, + // u -> u + 0, 1.0, + // v -> v + 1.0 - edgeThickness, 1.0, ico, flip ); + } + + @SideOnly(Side.CLIENT) + protected void renderFace(int x, int y, int z, Block block, Icon ico, RenderBlocks renderer, ForgeDirection orientation) + { + switch (orientation) + { + case NORTH: + renderer.renderFaceZNeg( block, x, y, z, ico ); + break; + case SOUTH: + renderer.renderFaceZPos( block, x, y, z, ico ); + break; + case EAST: + renderer.renderFaceXPos( block, x, y, z, ico ); + break; + case WEST: + renderer.renderFaceXNeg( block, x, y, z, ico ); + break; + case UP: + renderer.renderFaceYPos( block, x, y, z, ico ); + break; + case DOWN: + renderer.renderFaceYNeg( block, x, y, z, ico ); + break; + default: + break; + } + } + + public void selectFace(RenderBlocks renderer, ForgeDirection west, ForgeDirection up, ForgeDirection forward, int u1, int u2, int v1, int v2) + { + v1 = 16 - v1; + v2 = 16 - v2; + + double minX = (forward.offsetX > 0 ? 1 : 0) + mapFaceUV( west.offsetX, u1 ) + mapFaceUV( up.offsetX, v1 ); + double minY = (forward.offsetY > 0 ? 1 : 0) + mapFaceUV( west.offsetY, u1 ) + mapFaceUV( up.offsetY, v1 ); + double minZ = (forward.offsetZ > 0 ? 1 : 0) + mapFaceUV( west.offsetZ, u1 ) + mapFaceUV( up.offsetZ, v1 ); + + double maxX = (forward.offsetX > 0 ? 1 : 0) + mapFaceUV( west.offsetX, u2 ) + mapFaceUV( up.offsetX, v2 ); + double maxY = (forward.offsetY > 0 ? 1 : 0) + mapFaceUV( west.offsetY, u2 ) + mapFaceUV( up.offsetY, v2 ); + double maxZ = (forward.offsetZ > 0 ? 1 : 0) + mapFaceUV( west.offsetZ, u2 ) + mapFaceUV( up.offsetZ, v2 ); + + renderer.renderMinX = Math.max( 0.0, Math.min( minX, maxX ) - 0.001 ); + renderer.renderMaxX = Math.min( 1.0, Math.max( minX, maxX ) + 0.001 ); + + renderer.renderMinY = Math.max( 0.0, Math.min( minY, maxY ) - 0.001 ); + renderer.renderMaxY = Math.min( 1.0, Math.max( minY, maxY ) + 0.001 ); + + renderer.renderMinZ = Math.max( 0.0, Math.min( minZ, maxZ ) - 0.001 ); + renderer.renderMaxZ = Math.min( 1.0, Math.max( minZ, maxZ ) + 0.001 ); + } + + private double mapFaceUV(int offset, int uv) + { + if ( offset == 0 ) + return 0; + + if ( offset > 0 ) + return (double) uv / 16.0; + + return (16.0 - (double) uv) / 16.0; + } + + public void renderTile(AEBaseBlock block, AEBaseTile tile, Tessellator tess, double x, double y, double z, float f, RenderBlocks renderer) + { + ForgeDirection forward = ForgeDirection.SOUTH; + ForgeDirection up = ForgeDirection.UP; + + renderer.uvRotateBottom = renderer.uvRotateTop = renderer.uvRotateEast = renderer.uvRotateWest = renderer.uvRotateNorth = renderer.uvRotateSouth = 0; + + applyTESRRotation( x, y, z, forward, up ); + + Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.locationBlocksTexture ); + RenderHelper.disableStandardItemLighting(); + + if ( Minecraft.isAmbientOcclusionEnabled() ) + GL11.glShadeModel( GL11.GL_SMOOTH ); + else + GL11.glShadeModel( GL11.GL_FLAT ); + + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + + tess.setTranslation( -tile.xCoord, -tile.yCoord, -tile.zCoord ); + tess.startDrawingQuads(); + + // note that this is a terrible approach... + renderer.setRenderBoundsFromBlock( block ); + renderer.renderStandardBlock( block, tile.xCoord, tile.yCoord, tile.zCoord ); + + tess.draw(); + tess.setTranslation( 0, 0, 0 ); + RenderHelper.enableStandardItemLighting(); + + renderer.uvRotateBottom = renderer.uvRotateTop = renderer.uvRotateEast = renderer.uvRotateWest = renderer.uvRotateNorth = renderer.uvRotateSouth = 0; + } + + public void doRenderItem(ItemStack itemstack, TileEntity par1EntityItemFrame) + { + if ( itemstack != null ) + { + EntityItem entityitem = new EntityItem( par1EntityItemFrame.worldObj, 0.0D, 0.0D, 0.0D, itemstack ); + entityitem.getEntityItem().stackSize = 1; + + // set all this stuff and then do shit? meh? + entityitem.hoverStart = 0; + entityitem.age = 0; + entityitem.rotationYaw = 0; + + GL11.glPushMatrix(); + GL11.glTranslatef( 0, -0.14F, 0 ); + + RenderItem.renderInFrame = true; + RenderManager.instance.renderEntityWithPosYaw( entityitem, 0.0D, 0.0D, 0.0D, 0.0F, 0.0F ); + RenderItem.renderInFrame = false; + + GL11.glPopMatrix(); + } + } + +} diff --git a/client/render/BlockRenderInfo.java b/client/render/BlockRenderInfo.java new file mode 100644 index 00000000..c93399a8 --- /dev/null +++ b/client/render/BlockRenderInfo.java @@ -0,0 +1,122 @@ +package appeng.client.render; + +import appeng.client.texture.FlipableIcon; +import appeng.client.texture.TmpFlipableIcon; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +public class BlockRenderInfo +{ + + public BlockRenderInfo(BaseBlockRender inst) { + rendererInstance = inst; + } + + final public BaseBlockRender rendererInstance; + + private boolean useTmp = false; + private TmpFlipableIcon tmpTopIcon = new TmpFlipableIcon(); + private TmpFlipableIcon tmpBottomIcon = new TmpFlipableIcon(); + private TmpFlipableIcon tmpSouthIcon = new TmpFlipableIcon(); + private TmpFlipableIcon tmpNorthIcon = new TmpFlipableIcon(); + private TmpFlipableIcon tmpEastIcon = new TmpFlipableIcon(); + private TmpFlipableIcon tmpWestIcon = new TmpFlipableIcon(); + + private FlipableIcon topIcon = null; + private FlipableIcon bottomIcon = null; + private FlipableIcon southIcon = null; + private FlipableIcon northIcon = null; + private FlipableIcon eastIcon = null; + private FlipableIcon westIcon = null; + + public void updateIcons(FlipableIcon Bottom, FlipableIcon Top, FlipableIcon North, FlipableIcon South, FlipableIcon East, + FlipableIcon West) + { + topIcon = Top; + bottomIcon = Bottom; + southIcon = South; + northIcon = North; + eastIcon = East; + westIcon = West; + + } + + public void setTemporaryRenderIcon(Icon icon) + { + if ( icon == null ) + useTmp = false; + else + { + useTmp = true; + tmpTopIcon.setOriginal( icon ); + tmpBottomIcon.setOriginal( icon ); + tmpSouthIcon.setOriginal( icon ); + tmpNorthIcon.setOriginal( icon ); + tmpEastIcon.setOriginal( icon ); + tmpWestIcon.setOriginal( icon ); + } + } + + public void setTemporaryRenderIcons(Icon nTopIcon, Icon nBottomIcon, Icon nSouthIcon, Icon nNorthIcon, Icon nEastIcon, + Icon nWestIcon) + { + tmpTopIcon.setOriginal( nTopIcon == null ? getTexture( ForgeDirection.UP ) : nTopIcon ); + tmpBottomIcon.setOriginal( nBottomIcon == null ? getTexture( ForgeDirection.DOWN ) : nBottomIcon ); + tmpSouthIcon.setOriginal( nSouthIcon == null ? getTexture( ForgeDirection.SOUTH ) : nSouthIcon ); + tmpNorthIcon.setOriginal( nNorthIcon == null ? getTexture( ForgeDirection.NORTH ) : nNorthIcon ); + tmpEastIcon.setOriginal( nEastIcon == null ? getTexture( ForgeDirection.EAST ) : nEastIcon ); + tmpWestIcon.setOriginal( nWestIcon == null ? getTexture( ForgeDirection.WEST ) : nWestIcon ); + useTmp = true; + } + + public FlipableIcon getTexture(ForgeDirection dir) + { + if ( useTmp ) + { + switch (dir) + { + case DOWN: + return tmpBottomIcon; + case UP: + return tmpTopIcon; + case NORTH: + return tmpNorthIcon; + case SOUTH: + return tmpSouthIcon; + case EAST: + return tmpEastIcon; + case WEST: + return tmpWestIcon; + default: + break; + } + } + + switch (dir) + { + case DOWN: + return bottomIcon; + case UP: + return topIcon; + case NORTH: + return northIcon; + case SOUTH: + return southIcon; + case EAST: + return eastIcon; + case WEST: + return westIcon; + default: + break; + } + + return topIcon; + } + + public boolean isValid() + { + return topIcon != null && bottomIcon != null && southIcon != null && northIcon != null && eastIcon != null + && westIcon != null; + } + +} diff --git a/client/render/BusRenderHelper.java b/client/render/BusRenderHelper.java new file mode 100644 index 00000000..d5f3dcca --- /dev/null +++ b/client/render/BusRenderHelper.java @@ -0,0 +1,254 @@ +package appeng.client.render; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.parts.IPartRenderHelper; +import appeng.block.AEBaseBlock; + +public class BusRenderHelper implements IPartRenderHelper +{ + + final public static BusRenderHelper instance = new BusRenderHelper(); + + double minX = 0; + double minY = 0; + double minZ = 0; + double maxX = 16; + double maxY = 16; + double maxZ = 16; + + AEBaseBlock blk = (AEBaseBlock) AEApi.instance().blocks().blockMultiPart.block(); + BaseBlockRender bbr = new BaseBlockRender(); + + public ForgeDirection ax; + public ForgeDirection ay; + public ForgeDirection az; + + int color = 0xffffff; + + @Override + public void setBounds(float minx, float miny, float minz, float maxx, float maxy, float maxz) + { + minX = minx; + minY = miny; + minZ = minz; + maxX = maxx; + maxY = maxy; + maxZ = maxz; + } + + @Override + public void setInvColor(int newColor) + { + color = newColor; + } + + @Override + public void setTexture(Icon ico) + { + blk.getRendererInstance().setTemporaryRenderIcon( ico ); + } + + @Override + public void setTexture(Icon Down, Icon Up, Icon North, Icon South, Icon West, Icon East) + { + Icon list[] = new Icon[6]; + + list[0] = Down; + list[1] = Up; + list[2] = North; + list[3] = South; + list[4] = West; + list[5] = East; + + blk.getRendererInstance().setTemporaryRenderIcons( list[mapRotation( ForgeDirection.UP ).ordinal()], + list[mapRotation( ForgeDirection.DOWN ).ordinal()], list[mapRotation( ForgeDirection.SOUTH ).ordinal()], + list[mapRotation( ForgeDirection.NORTH ).ordinal()], list[mapRotation( ForgeDirection.EAST ).ordinal()], + list[mapRotation( ForgeDirection.WEST ).ordinal()] ); + } + + public ForgeDirection mapRotation(ForgeDirection dir) + { + ForgeDirection forward = az; + ForgeDirection up = ay; + ForgeDirection west = ForgeDirection.UNKNOWN; + + if ( forward == null || up == null ) + return dir; + + int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + for (ForgeDirection dx : ForgeDirection.VALID_DIRECTIONS) + if ( dx.offsetX == west_x && dx.offsetY == west_y && dx.offsetZ == west_z ) + west = dx; + + if ( dir.equals( forward ) ) + return ForgeDirection.SOUTH; + if ( dir.equals( forward.getOpposite() ) ) + return ForgeDirection.NORTH; + + if ( dir.equals( up ) ) + return ForgeDirection.UP; + if ( dir.equals( up.getOpposite() ) ) + return ForgeDirection.DOWN; + + if ( dir.equals( west ) ) + return ForgeDirection.WEST; + if ( dir.equals( west.getOpposite() ) ) + return ForgeDirection.EAST; + + return ForgeDirection.UNKNOWN; + } + + @Override + public void renderInventoryBox(RenderBlocks renderer) + { + renderer.setRenderBounds( minX / 16.0, minY / 16.0, minZ / 16.0, maxX / 16.0, maxY / 16.0, maxZ / 16.0 ); + bbr.renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, Tessellator.instance, color, renderer ); + } + + @Override + public void renderInventoryFace(Icon icon, ForgeDirection face, RenderBlocks renderer) + { + renderer.setRenderBounds( minX / 16.0, minY / 16.0, minZ / 16.0, maxX / 16.0, maxY / 16.0, maxZ / 16.0 ); + setTexture( icon ); + bbr.renderInvBlock( EnumSet.of( face ), blk, Tessellator.instance, color, renderer ); + } + + @Override + public void renderBlock(int x, int y, int z, RenderBlocks renderer) + { + AEBaseBlock blk = (AEBaseBlock) AEApi.instance().blocks().blockMultiPart.block(); + BlockRenderInfo info = blk.getRendererInstance(); + ForgeDirection forward = BusRenderHelper.instance.az; + ForgeDirection up = BusRenderHelper.instance.ay; + + renderer.uvRotateBottom = info.getTexture( ForgeDirection.DOWN ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.DOWN, forward, up ) ); + renderer.uvRotateTop = info.getTexture( ForgeDirection.UP ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.UP, forward, up ) ); + + renderer.uvRotateEast = info.getTexture( ForgeDirection.EAST ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.EAST, forward, up ) ); + renderer.uvRotateWest = info.getTexture( ForgeDirection.WEST ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.WEST, forward, up ) ); + + renderer.uvRotateNorth = info.getTexture( ForgeDirection.NORTH ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.NORTH, forward, up ) ); + renderer.uvRotateSouth = info.getTexture( ForgeDirection.SOUTH ).setFlip( BaseBlockRender.getOrientation( ForgeDirection.SOUTH, forward, up ) ); + + bbr.renderBlockBounds( renderer, minX, minY, minZ, maxX, maxY, maxZ, ax, ay, az ); + + int blkId = renderer.blockAccess.getBlockId( x, y, z ); + if ( Block.blocksList[blkId] == null ) + return; + + renderer.renderStandardBlock( blk, x, y, z ); + } + + @Override + public Block getBlock() + { + return AEApi.instance().blocks().blockMultiPart.block(); + } + + public void prepareBounds(RenderBlocks renderer) + { + bbr.renderBlockBounds( renderer, minX, minY, minZ, maxX, maxY, maxZ, ax, ay, az ); + } + + public void renderBlockCurrentBounds(int x, int y, int z, RenderBlocks renderer) + { + int blkId = renderer.blockAccess.getBlockId( x, y, z ); + if ( Block.blocksList[blkId] == null ) + return; + + renderer.renderStandardBlock( blk, x, y, z ); + } + + @Override + public void renderFaceCutout(int x, int y, int z, Icon ico, ForgeDirection face, float edgeThickness, RenderBlocks renderer) + { + switch (face) + { + case DOWN: + face = ay.getOpposite(); + break; + case EAST: + face = ax; + break; + case NORTH: + face = az.getOpposite(); + break; + case SOUTH: + face = az; + break; + case UP: + face = ay; + break; + case WEST: + face = ax.getOpposite(); + break; + case UNKNOWN: + break; + default: + break; + } + + bbr.renderCutoutFace( blk, ico, x, y, z, renderer, face, edgeThickness ); + } + + @Override + public void renderFace(int x, int y, int z, Icon ico, ForgeDirection face, RenderBlocks renderer) + { + prepareBounds( renderer ); + switch (face) + { + case DOWN: + face = ay.getOpposite(); + break; + case EAST: + face = ax; + break; + case NORTH: + face = az.getOpposite(); + break; + case SOUTH: + face = az; + break; + case UP: + face = ay; + break; + case WEST: + face = ax.getOpposite(); + break; + case UNKNOWN: + break; + default: + break; + } + + bbr.renderFace( x, y, z, blk, ico, renderer, face ); + } + + @Override + public ForgeDirection getWorldX() + { + return ax; + } + + @Override + public ForgeDirection getWorldY() + { + return ay; + } + + @Override + public ForgeDirection getWorldZ() + { + return az; + } +} diff --git a/client/render/BusRenderer.java b/client/render/BusRenderer.java new file mode 100644 index 00000000..f783ea1f --- /dev/null +++ b/client/render/BusRenderer.java @@ -0,0 +1,85 @@ +package appeng.client.render; + +import java.util.HashMap; + +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraftforge.client.IItemRenderer; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.parts.IPartItem; +import appeng.api.parts.IPart; +import appeng.api.parts.IFacadePart; +import appeng.client.ClientHelper; +import appeng.facade.IFacadeItem; +import appeng.util.Platform; + +public class BusRenderer implements IItemRenderer +{ + + public static final BusRenderer instance = new BusRenderer(); + + public RenderBlocksWorkaround renderer = new RenderBlocksWorkaround(); + public static final HashMap renderPart = new HashMap(); + + public IPart getRenderer(ItemStack is, IPartItem c) + { + int id = (is.getItem().itemID << Platform.DEF_OFFSET) | is.getItemDamage(); + + IPart part = renderPart.get( id ); + if ( part == null ) + { + part = c.createPartFromItemStack( is ); + renderPart.put( id, part ); + } + + return part; + } + + @Override + public boolean handleRenderType(ItemStack item, ItemRenderType type) + { + return true; + } + + @Override + public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) + { + return true; + } + + @Override + public void renderItem(ItemRenderType type, ItemStack item, Object... data) + { + GL11.glPushMatrix(); + if ( type == ItemRenderType.ENTITY ) + GL11.glTranslatef( -0.5f, -0.5f, -0.5f ); + if ( type == ItemRenderType.INVENTORY ) + GL11.glTranslatef( 0.0f, -0.1f, 0.0f ); + + GL11.glTranslated( 0.2, 0.3, 0.0 ); + + GL11.glColor4f( 1, 1, 1, 1 ); + Tessellator.instance.setColorOpaque_F( 1, 1, 1 ); + + BusRenderHelper.instance.setBounds( 0, 0, 0, 1, 1, 1 ); + BusRenderHelper.instance.setTexture( null ); + BusRenderHelper.instance.setInvColor( 0xffffff ); + renderer.blockAccess = ClientHelper.proxy.getWorld(); + + if ( item.getItem() instanceof IFacadeItem ) + { + IFacadeItem fi = (IFacadeItem) item.getItem(); + IFacadePart fp = fi.createPartFromItemStack( item, ForgeDirection.SOUTH ); + + if ( fp != null ) + fp.renderInventory( BusRenderHelper.instance, renderer ); + } + else + getRenderer( item, (IPartItem) item.getItem() ).renderInventory( BusRenderHelper.instance, renderer ); + + GL11.glPopMatrix(); + } +} diff --git a/client/render/ItemRenderer.java b/client/render/ItemRenderer.java new file mode 100644 index 00000000..6befdae3 --- /dev/null +++ b/client/render/ItemRenderer.java @@ -0,0 +1,37 @@ +package appeng.client.render; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.client.IItemRenderer; + +import org.lwjgl.opengl.GL11; + +public class ItemRenderer implements IItemRenderer +{ + + public static final ItemRenderer instance = new ItemRenderer(); + + @Override + public boolean handleRenderType(ItemStack item, ItemRenderType type) + { + return true; + } + + @Override + public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) + { + return true; + } + + @Override + public void renderItem(ItemRenderType type, ItemStack item, Object... data) + { + GL11.glPushMatrix(); + if ( type == ItemRenderType.ENTITY ) + GL11.glTranslatef( -0.5f, -0.5f, -0.5f ); + if ( type == ItemRenderType.INVENTORY ) + GL11.glTranslatef( 0.0f, -0.1f, 0.0f ); + WorldRender.instance.renderItemBlock( item ); + GL11.glPopMatrix(); + } + +} diff --git a/client/render/RenderBlocksWorkaround.java b/client/render/RenderBlocksWorkaround.java new file mode 100644 index 00000000..6a118fa8 --- /dev/null +++ b/client/render/RenderBlocksWorkaround.java @@ -0,0 +1,499 @@ +package appeng.client.render; + +import java.lang.reflect.Field; +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +public class RenderBlocksWorkaround extends RenderBlocks +{ + + public boolean calculations = true; + public EnumSet faces = EnumSet.allOf( ForgeDirection.class ); + + private Icon rXPos = null; + private Icon rXNeg = null; + private Icon rYPos = null; + private Icon rYNeg = null; + private Icon rZPos = null; + private Icon rZNeg = null; + + private boolean isAO = false; + + private int bXPos = 0; + private int bXNeg = 0; + private int bYPos = 0; + private int bYNeg = 0; + private int bZPos = 0; + private int bZNeg = 0; + + private int aoXPos[] = new int[4]; + private int aoXNeg[] = new int[4]; + private int aoYPos[] = new int[4]; + private int aoYNeg[] = new int[4]; + private int aoZPos[] = new int[4]; + private int aoZNeg[] = new int[4]; + + private float foXPos[] = new float[12]; + private float foXNeg[] = new float[12]; + private float foYPos[] = new float[12]; + private float foYNeg[] = new float[12]; + private float foZPos[] = new float[12]; + private float foZNeg[] = new float[12]; + + public boolean isFacade = false; + + Field fBrightness; + + public int getCurrentBrightness() + { + try + { + if ( fBrightness == null ) + { + fBrightness = Tessellator.class.getDeclaredField( "brightness" ); + fBrightness.setAccessible( true ); + } + return (Integer) fBrightness.get( Tessellator.instance ); + } + catch (Throwable t) + { + return 0; + } + } + + public void setTexture(Icon ico) + { + rXPos = rXNeg = rYPos = rYNeg = rZPos = rZNeg = ico; + } + + public boolean renderStandardBlockNoCalculations(Block b, int x, int y, int z) + { + Tessellator.instance.setBrightness( bXPos ); + restoreAO( aoXPos, foXPos ); + renderFaceXPos( b, x, y, z, rXPos ); + + Tessellator.instance.setBrightness( bXNeg ); + restoreAO( aoXNeg, foXNeg ); + renderFaceXNeg( b, x, y, z, rXNeg ); + + Tessellator.instance.setBrightness( bYPos ); + restoreAO( aoYPos, foYPos ); + renderFaceYPos( b, x, y, z, rYPos ); + + Tessellator.instance.setBrightness( bYNeg ); + restoreAO( aoYNeg, foYNeg ); + renderFaceYNeg( b, x, y, z, rYNeg ); + + Tessellator.instance.setBrightness( bZPos ); + restoreAO( aoZPos, foZPos ); + renderFaceZPos( b, x, y, z, rZPos ); + + Tessellator.instance.setBrightness( bZNeg ); + restoreAO( aoZNeg, foZNeg ); + renderFaceZNeg( b, x, y, z, rZNeg ); + + return true; + } + + private void restoreAO(int[] z, float[] c) + { + brightnessBottomLeft = z[0]; + brightnessBottomRight = z[1]; + brightnessTopLeft = z[2]; + brightnessTopRight = z[3]; + + colorRedTopLeft = c[0]; + colorGreenTopLeft = c[1]; + colorBlueTopLeft = c[2]; + colorRedBottomLeft = c[3]; + colorGreenBottomLeft = c[4]; + colorBlueBottomLeft = c[5]; + colorRedBottomRight = c[6]; + colorGreenBottomRight = c[7]; + colorBlueBottomRight = c[8]; + colorRedTopRight = c[9]; + colorGreenTopRight = c[10]; + colorBlueTopRight = c[11]; + } + + private void saveAO(int[] z, float[] c) + { + z[0] = brightnessBottomLeft; + z[1] = brightnessBottomRight; + z[2] = brightnessTopLeft; + z[3] = brightnessTopRight; + + c[0] = colorRedTopLeft; + c[1] = colorGreenTopLeft; + c[2] = colorBlueTopLeft; + c[3] = colorRedBottomLeft; + c[4] = colorGreenBottomLeft; + c[5] = colorBlueBottomLeft; + c[6] = colorRedBottomRight; + c[7] = colorGreenBottomRight; + c[8] = colorBlueBottomRight; + c[9] = colorRedTopRight; + c[10] = colorGreenTopRight; + c[11] = colorBlueTopRight; + } + + @Override + public boolean renderStandardBlock(Block par1Block, int par2, int par3, int par4) + { + try + { + if ( calculations ) + return super.renderStandardBlock( par1Block, par2, par3, par4 ); + else + { + enableAO = isAO; + return renderStandardBlockNoCalculations( par1Block, par2, par3, par4 ); + } + } + catch (Throwable t) + { + t.printStackTrace(); + // meh + } + return false; + } + + @Override + public void renderFaceXNeg(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.WEST ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinZ * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxZ * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMaxY * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMinY * 16.0D ); + + double d11 = par2 + this.renderMinX; + double d12 = par4 + this.renderMinY; + double d13 = par4 + this.renderMaxY; + double d14 = par6 + this.renderMinZ; + double d15 = par6 + this.renderMaxZ; + + if ( this.enableAO ) + { + partialLightingColoring( renderMaxY, renderMaxZ ); + tessellator.addVertexWithUV( d11, d13, d15, d4, d5 ); + partialLightingColoring( renderMaxY, renderMinZ ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + partialLightingColoring( renderMinY, renderMinZ ); + tessellator.addVertexWithUV( d11, d12, d14, d3, d6 ); + partialLightingColoring( renderMinY, renderMaxZ ); + tessellator.addVertexWithUV( d11, d12, d15, d4, d6 ); + } + else + { + tessellator.addVertexWithUV( d11, d13, d15, d4, d5 ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + tessellator.addVertexWithUV( d11, d12, d14, d3, d6 ); + tessellator.addVertexWithUV( d11, d12, d15, d4, d6 ); + } + } + else + super.renderFaceXNeg( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rXNeg = par8Icon; + saveAO( aoXNeg, foXNeg ); + bXNeg = getCurrentBrightness(); + } + } + + @Override + public void renderFaceXPos(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.EAST ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinZ * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxZ * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMaxY * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMinY * 16.0D ); + + double d11 = par2 + this.renderMaxX; + double d12 = par4 + this.renderMinY; + double d13 = par4 + this.renderMaxY; + double d14 = par6 + this.renderMinZ; + double d15 = par6 + this.renderMaxZ; + + if ( this.enableAO ) + { + partialLightingColoring( 1.0 - renderMinY, renderMaxZ ); + tessellator.addVertexWithUV( d11, d12, d15, d4, d6 ); + partialLightingColoring( 1.0 - renderMinY, renderMinZ ); + tessellator.addVertexWithUV( d11, d12, d14, d3, d6 ); + partialLightingColoring( 1.0 - renderMaxY, renderMinZ ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + partialLightingColoring( 1.0 - renderMaxY, renderMaxZ ); + tessellator.addVertexWithUV( d11, d13, d15, d4, d5 ); + } + else + { + tessellator.addVertexWithUV( d11, d12, d15, d4, d6 ); + tessellator.addVertexWithUV( d11, d12, d14, d3, d6 ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + tessellator.addVertexWithUV( d11, d13, d15, d4, d5 ); + } + } + else + super.renderFaceXPos( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rXPos = par8Icon; + saveAO( aoXPos, foXPos ); + bXPos = getCurrentBrightness(); + } + } + + private void partialLightingColoring(double u, double v) + { + double rA = colorRedTopLeft * u + (1.0 - u) * colorRedTopRight; + double rB = colorRedBottomLeft * u + (1.0 - u) * colorRedBottomRight; + float r = (float) (rA * v + rB * (1.0 - v)); + + double gA = colorGreenTopLeft * u + (1.0 - u) * colorGreenTopRight; + double gB = colorGreenBottomLeft * u + (1.0 - u) * colorGreenBottomRight; + float g = (float) (gA * v + gB * (1.0 - v)); + + double bA = colorBlueTopLeft * u + (1.0 - u) * colorBlueTopRight; + double bB = colorBlueBottomLeft * u + (1.0 - u) * colorBlueBottomRight; + float b = (float) (bA * v + bB * (1.0 - v)); + + double highA = (brightnessTopLeft >> 16 & 255) * u + (1.0 - u) * (brightnessTopRight >> 16 & 255); + double highB = (brightnessBottomLeft >> 16 & 255) * u + (1.0 - u) * (brightnessBottomRight >> 16 & 255); + int high = ((int) (highA * v + highB * (1.0 - v))) & 255; + + double lowA = ((brightnessTopLeft & 255)) * u + (1.0 - u) * ((brightnessTopRight & 255)); + double lowB = ((brightnessBottomLeft & 255)) * u + (1.0 - u) * ((brightnessBottomRight & 255)); + int low = ((int) (lowA * v + lowB * (1.0 - v))) & 255; + + int out = (high << 16) | low; + + Tessellator.instance.setColorOpaque_F( r, g, b ); + Tessellator.instance.setBrightness( out ); + } + + @Override + public void renderFaceYNeg(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.DOWN ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinX * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxX * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( this.renderMinZ * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( this.renderMaxZ * 16.0D ); + + double d11 = par2 + this.renderMinX; + double d12 = par2 + this.renderMaxX; + double d13 = par4 + this.renderMinY; + double d14 = par6 + this.renderMinZ; + double d15 = par6 + this.renderMaxZ; + + if ( this.enableAO ) + { + partialLightingColoring( 1.0 - renderMinX, renderMaxZ ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + partialLightingColoring( 1.0 - renderMinX, renderMinZ ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + partialLightingColoring( 1.0 - renderMaxX, renderMinZ ); + tessellator.addVertexWithUV( d12, d13, d14, d4, d5 ); + partialLightingColoring( 1.0 - renderMaxX, renderMaxZ ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + } + else + { + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + tessellator.addVertexWithUV( d12, d13, d14, d4, d5 ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + } + } + else + super.renderFaceYNeg( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rYNeg = par8Icon; + saveAO( aoYNeg, foYNeg ); + bYNeg = getCurrentBrightness(); + } + } + + @Override + public void renderFaceYPos(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.UP ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinX * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxX * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( this.renderMinZ * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( this.renderMaxZ * 16.0D ); + + double d11 = par2 + this.renderMinX; + double d12 = par2 + this.renderMaxX; + double d13 = par4 + this.renderMaxY; + double d14 = par6 + this.renderMinZ; + double d15 = par6 + this.renderMaxZ; + + if ( this.enableAO ) + { + partialLightingColoring( this.renderMaxX, renderMaxZ ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + partialLightingColoring( this.renderMaxX, renderMinZ ); + tessellator.addVertexWithUV( d12, d13, d14, d4, d5 ); + partialLightingColoring( this.renderMinX, renderMinZ ); + tessellator.addVertexWithUV( d11, d13, d14, d3, d5 ); + partialLightingColoring( this.renderMinX, renderMaxZ ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + } + else + { + tessellator.addVertexWithUV( d12, d13, d15, d3, d6 ); + tessellator.addVertexWithUV( d12, d13, d14, d3, d5 ); + tessellator.addVertexWithUV( d11, d13, d14, d4, d5 ); + tessellator.addVertexWithUV( d11, d13, d15, d4, d6 ); + } + } + else + super.renderFaceYPos( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rYPos = par8Icon; + saveAO( aoYPos, foYPos ); + bYPos = getCurrentBrightness(); + } + } + + @Override + public void renderFaceZNeg(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.NORTH ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinX * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxX * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMaxY * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMinY * 16.0D ); + + double d11 = par2 + this.renderMinX; + double d12 = par2 + this.renderMaxX; + double d13 = par4 + this.renderMinY; + double d14 = par4 + this.renderMaxY; + double d15 = par6 + this.renderMinZ; + + if ( this.enableAO ) + { + partialLightingColoring( renderMaxY, 1.0 - renderMinX ); + tessellator.addVertexWithUV( d11, d14, d15, d3, d5 ); + partialLightingColoring( renderMaxY, 1.0 - renderMaxX ); + tessellator.addVertexWithUV( d12, d14, d15, d4, d5 ); + partialLightingColoring( renderMinY, 1.0 - renderMaxX ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + partialLightingColoring( renderMinY, 1.0 - renderMinX ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + } + else + { + tessellator.addVertexWithUV( d11, d14, d15, d3, d5 ); + tessellator.addVertexWithUV( d12, d14, d15, d4, d5 ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + } + } + else + super.renderFaceZNeg( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rZNeg = par8Icon; + saveAO( aoZNeg, foZNeg ); + bZNeg = getCurrentBrightness(); + } + } + + @Override + public void renderFaceZPos(Block par1Block, double par2, double par4, double par6, Icon par8Icon) + { + if ( faces.contains( ForgeDirection.SOUTH ) ) + { + if ( isFacade ) + { + Tessellator tessellator = Tessellator.instance; + + double d3 = (double) par8Icon.getInterpolatedU( this.renderMinX * 16.0D ); + double d4 = (double) par8Icon.getInterpolatedU( this.renderMaxX * 16.0D ); + double d5 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMaxY * 16.0D ); + double d6 = (double) par8Icon.getInterpolatedV( 16.0D - this.renderMinY * 16.0D ); + + double d11 = par2 + this.renderMinX; + double d12 = par2 + this.renderMaxX; + double d13 = par4 + this.renderMinY; + double d14 = par4 + this.renderMaxY; + double d15 = par6 + this.renderMaxZ; + + if ( this.enableAO ) + { + partialLightingColoring( 1.0 - renderMinX, renderMaxY ); + tessellator.addVertexWithUV( d11, d14, d15, d3, d5 ); + partialLightingColoring( 1.0 - renderMinX, renderMinY ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + partialLightingColoring( 1.0 - renderMaxX, renderMinY ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + partialLightingColoring( 1.0 - renderMaxX, renderMaxY ); + tessellator.addVertexWithUV( d12, d14, d15, d4, d5 ); + } + else + { + tessellator.addVertexWithUV( d11, d14, d15, d3, d5 ); + tessellator.addVertexWithUV( d11, d13, d15, d3, d6 ); + tessellator.addVertexWithUV( d12, d13, d15, d4, d6 ); + tessellator.addVertexWithUV( d12, d14, d15, d4, d5 ); + } + } + else + super.renderFaceZPos( par1Block, par2, par4, par6, par8Icon ); + } + else + { + isAO = enableAO; + rZPos = par8Icon; + saveAO( aoZPos, foZPos ); + bZPos = getCurrentBrightness(); + } + } +} diff --git a/client/render/TESRWrapper.java b/client/render/TESRWrapper.java new file mode 100644 index 00000000..085c8316 --- /dev/null +++ b/client/render/TESRWrapper.java @@ -0,0 +1,66 @@ +package appeng.client.render; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; + +import org.lwjgl.opengl.GL11; + +import appeng.block.AEBaseBlock; +import appeng.tile.AEBaseTile; +import cpw.mods.fml.common.FMLLog; + +public class TESRWrapper extends TileEntitySpecialRenderer +{ + + final public RenderBlocks rbinstance = new RenderBlocks(); + + final BaseBlockRender blkRender; + final double MAX_DISTANCE; + + public TESRWrapper(BaseBlockRender render) { + blkRender = render; + MAX_DISTANCE = blkRender.getTesrRenderDistance(); + } + + @Override + final public void renderTileEntityAt(TileEntity te, double x, double y, double z, float f) + { + if ( Math.abs( x ) > MAX_DISTANCE || Math.abs( y ) > MAX_DISTANCE || Math.abs( z ) > MAX_DISTANCE ) + return; + + try + { + Block b = te.getBlockType(); + Tessellator tess = Tessellator.instance; + if ( tess.isDrawing ) + return; + + if ( b instanceof AEBaseBlock && te instanceof AEBaseTile ) + { + + GL11.glPushMatrix(); + GL11.glPushAttrib( GL11.GL_ALL_ATTRIB_BITS ); + + rbinstance.blockAccess = te.worldObj; + blkRender.renderTile( (AEBaseBlock) b, (AEBaseTile) te, tess, x, y, z, f, rbinstance ); + + if ( tess.isDrawing ) + throw new RuntimeException( "Error durring rendering." ); + + GL11.glPopAttrib(); + GL11.glPopMatrix(); + } + } + catch (Throwable t) + { + FMLLog.severe( "Hi, Looks like there was a crash while rendering something..." ); + t.printStackTrace(); + FMLLog.severe( "MC will now crash ( probobly )!" ); + throw new RuntimeException( t ); + } + + } +} diff --git a/client/render/WorldRender.java b/client/render/WorldRender.java new file mode 100644 index 00000000..03f7763a --- /dev/null +++ b/client/render/WorldRender.java @@ -0,0 +1,67 @@ +package appeng.client.render; + +import java.util.HashMap; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; +import cpw.mods.fml.client.registry.RenderingRegistry; + +public class WorldRender implements ISimpleBlockRenderingHandler +{ + + private RenderBlocks renderer = new RenderBlocks(); + final int renderID = RenderingRegistry.getNextAvailableRenderId(); + public static final WorldRender instance = new WorldRender(); + + public HashMap blockRenders = new HashMap(); + + void setRender(AEBaseBlock in, BaseBlockRender r) + { + blockRenders.put( in, r ); + } + + private WorldRender() { + } + + @Override + public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer) + { + // wtf is this for? + } + + @Override + public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) + { + AEBaseBlock blk = (AEBaseBlock) block; + renderer.setRenderBoundsFromBlock( block ); + return getRender( blk ).renderInWorld( blk, world, x, y, z, renderer ); + } + + @Override + public boolean shouldRender3DInInventory() + { + return true; + } + + @Override + public int getRenderId() + { + return renderID; + } + + public void renderItemBlock(ItemStack item) + { + AEBaseBlock block = (AEBaseBlock) Block.blocksList[item.itemID]; + renderer.setRenderBoundsFromBlock( block ); + getRender( block ).renderInventory( block, item, renderer ); + } + + private BaseBlockRender getRender(AEBaseBlock block) + { + return block.getRendererInstance().rendererInstance; + } +} diff --git a/client/render/blocks/RenderBlockCharger.java b/client/render/blocks/RenderBlockCharger.java new file mode 100644 index 00000000..8eca12b6 --- /dev/null +++ b/client/render/blocks/RenderBlockCharger.java @@ -0,0 +1,156 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import appeng.api.util.IOrientable; +import appeng.block.AEBaseBlock; +import appeng.block.misc.BlockCharger; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; + +public class RenderBlockCharger extends BaseBlockRender +{ + + public RenderBlockCharger() { + super( true, 30 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + Tessellator tess = Tessellator.instance; + + renderer.renderAllFaces = true; + setInvRenderBounds( renderer, 6, 1, 0, 10, 15, 2 ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + blk.getRendererInstance().setTemporaryRenderIcons( ExtraTextures.BlockChargerInside.getIcon(), null, null, null, null, null ); + + setInvRenderBounds( renderer, 2, 0, 2, 14, 3, 14 ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + setInvRenderBounds( renderer, 3, 3, 3, 13, 4, 13 ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + blk.getRendererInstance().setTemporaryRenderIcons( null, ExtraTextures.BlockChargerInside.getIcon(), null, null, null, null ); + + setInvRenderBounds( renderer, 2, 13, 2, 14, 16, 14 ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + setInvRenderBounds( renderer, 3, 12, 3, 13, 13, 13 ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + renderer.renderAllFaces = false; + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + preRenderInWorld( block, world, x, y, z, renderer ); + + BlockCharger blk = (BlockCharger) block; + + IOrientable te = getOrientable( block, world, x, y, z ); + + ForgeDirection fdy = te.getUp(); + ForgeDirection fdz = te.getForward(); + ForgeDirection fdx = Platform.crossProduct( fdz, fdy ).getOpposite(); + + renderer.renderAllFaces = true; + renderBlockBounds( renderer, 6, 1, 0, 10, 15, 2, fdx, fdy, fdz ); + boolean out = renderer.renderStandardBlock( blk, x, y, z ); + + blk.getRendererInstance().setTemporaryRenderIcons( ExtraTextures.BlockChargerInside.getIcon(), null, null, null, null, null ); + + renderBlockBounds( renderer, 2, 0, 2, 14, 3, 14, fdx, fdy, fdz ); + out = renderer.renderStandardBlock( blk, x, y, z ); + + renderBlockBounds( renderer, 3, 3, 3, 13, 4, 13, fdx, fdy, fdz ); + out = renderer.renderStandardBlock( blk, x, y, z ); + + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + blk.getRendererInstance().setTemporaryRenderIcons( null, ExtraTextures.BlockChargerInside.getIcon(), null, null, null, null ); + + renderBlockBounds( renderer, 2, 13, 2, 14, 16, 14, fdx, fdy, fdz ); + out = renderer.renderStandardBlock( blk, x, y, z ); + + renderBlockBounds( renderer, 3, 12, 3, 13, 13, 13, fdx, fdy, fdz ); + out = renderer.renderStandardBlock( blk, x, y, z ); + + renderer.renderAllFaces = false; + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + postRenderInWorld( renderer ); + return out; + } + + @Override + public void renderTile(AEBaseBlock block, AEBaseTile tile, Tessellator tess, double x, double y, double z, float f, RenderBlocks renderer) + { + ItemStack sis = null; + if ( tile instanceof IInventory ) + sis = ((IInventory) tile).getStackInSlot( 0 ); + + if ( sis != null ) + { + applyTESRRotation( x, y, z, tile.getForward(), tile.getUp() ); + + GL11.glPushMatrix(); + + try + { + GL11.glTranslatef( 0.5f, 0.45f, 0.5f ); + GL11.glScalef( 1.0f / 1.1f, 1.0f / 1.1f, 1.0f / 1.1f ); + GL11.glScalef( 1.0f, 1.0f, 1.0f ); + + int k = sis.itemID; + if ( sis.getItemSpriteNumber() == 0 && block != null && RenderBlocks.renderItemIn3d( Block.blocksList[k].getRenderType() ) ) + { + GL11.glRotatef( 25.0f, 1.0f, 0.0f, 0.0f ); + GL11.glRotatef( 15.0f, 0.0f, 1.0f, 0.0f ); + GL11.glRotatef( 30.0f, 0.0f, 1.0f, 0.0f ); + } + + int light = tile.worldObj.getLightBrightnessForSkyBlocks( tile.xCoord, tile.yCoord, tile.zCoord, 0 ); + int br = light;// << 20 | light << 4; + int var11 = br % 65536; + int var12 = br / 65536; + OpenGlHelper.setLightmapTextureCoords( OpenGlHelper.lightmapTexUnit, var11, var12 ); + + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL12.GL_RESCALE_NORMAL ); + tess.setColorOpaque_F( 1.0f, 1.0f, 1.0f ); + + doRenderItem( sis, tile ); + } + catch (Exception err) + { + err.printStackTrace(); + } + + GL11.glPopMatrix(); + } + } + +} diff --git a/client/render/blocks/RenderBlockController.java b/client/render/blocks/RenderBlockController.java new file mode 100644 index 00000000..9e2f8261 --- /dev/null +++ b/client/render/blocks/RenderBlockController.java @@ -0,0 +1,125 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; +import appeng.tile.networking.TileController; + +public class RenderBlockController extends BaseBlockRender +{ + + public RenderBlockController() { + super( false, 20 ); + } + + @Override + public boolean renderInWorld(AEBaseBlock blk, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + + boolean xx = world.getBlockTileEntity( x - 1, y, z ) instanceof TileController && world.getBlockTileEntity( x + 1, y, z ) instanceof TileController; + boolean yy = world.getBlockTileEntity( x, y - 1, z ) instanceof TileController && world.getBlockTileEntity( x, y + 1, z ) instanceof TileController; + boolean zz = world.getBlockTileEntity( x, y, z - 1 ) instanceof TileController && world.getBlockTileEntity( x, y, z + 1 ) instanceof TileController; + + int meta = world.getBlockMetadata( x, y, z ); + boolean hasPower = meta > 0; + boolean isConflict = meta == 2; + + ExtraTextures lights = null; + + if ( xx && !yy && !zz ) + { + if ( hasPower ) + { + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumnPowered.getIcon() ); + if ( isConflict ) + lights = ExtraTextures.BlockControllerColumnConflict; + else + lights = ExtraTextures.BlockControllerColumnLights; + } + else + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumn.getIcon() ); + + renderer.uvRotateEast = 1; + renderer.uvRotateWest = 1; + renderer.uvRotateTop = 1; + renderer.uvRotateBottom = 1; + } + else if ( !xx && yy && !zz ) + { + if ( hasPower ) + { + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumnPowered.getIcon() ); + if ( isConflict ) + lights = ExtraTextures.BlockControllerColumnConflict; + else + lights = ExtraTextures.BlockControllerColumnLights; + } + else + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumn.getIcon() ); + + renderer.uvRotateEast = 0; + renderer.uvRotateNorth = 0; + } + else if ( !xx && !yy && zz ) + { + if ( hasPower ) + { + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumnPowered.getIcon() ); + if ( isConflict ) + lights = ExtraTextures.BlockControllerColumnConflict; + else + lights = ExtraTextures.BlockControllerColumnLights; + } + else + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerColumn.getIcon() ); + + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 1; + renderer.uvRotateTop = 0; + } + else if ( (xx ? 1 : 0) + (yy ? 1 : 0) + (zz ? 1 : 0) >= 2 ) + { + int v = (Math.abs( x ) + Math.abs( y ) + Math.abs( z )) % 2; + renderer.uvRotateEast = renderer.uvRotateBottom = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + + if ( v == 0 ) + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerInsideA.getIcon() ); + else + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerInsideB.getIcon() ); + } + else + { + if ( hasPower ) + { + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.BlockControllerPowered.getIcon() ); + if ( isConflict ) + lights = ExtraTextures.BlockControllerConflict; + else + lights = ExtraTextures.BlockControllerLights; + } + else + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + } + + boolean out = renderer.renderStandardBlock( blk, x, y, z ); + if ( lights != null ) + { + Tessellator.instance.setColorOpaque_F( 1.0f, 1.0f, 1.0f ); + Tessellator.instance.setBrightness( 14 << 20 | 14 << 4 ); + renderer.renderFaceXNeg( blk, x, y, z, lights.getIcon() ); + renderer.renderFaceXPos( blk, x, y, z, lights.getIcon() ); + renderer.renderFaceYNeg( blk, x, y, z, lights.getIcon() ); + renderer.renderFaceYPos( blk, x, y, z, lights.getIcon() ); + renderer.renderFaceZNeg( blk, x, y, z, lights.getIcon() ); + renderer.renderFaceZPos( blk, x, y, z, lights.getIcon() ); + } + + blk.getRendererInstance().setTemporaryRenderIcon( null ); + renderer.uvRotateEast = renderer.uvRotateBottom = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + return out; + } +} diff --git a/client/render/blocks/RenderBlockCrank.java b/client/render/blocks/RenderBlockCrank.java new file mode 100644 index 00000000..30cb8880 --- /dev/null +++ b/client/render/blocks/RenderBlockCrank.java @@ -0,0 +1,87 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.tile.AEBaseTile; +import appeng.tile.grindstone.TileCrank; + +public class RenderBlockCrank extends BaseBlockRender +{ + + public RenderBlockCrank() { + super( true, 60 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + renderer.renderAllFaces = true; + + renderer.setRenderBounds( 0.5D - 0.05, 0.5D - 0.5, 0.5D - 0.05, 0.5D + 0.05, 0.5D + 0.3, 0.5D + 0.05 ); + super.renderInventory( blk, is, renderer ); + + renderer.setRenderBounds( 0.70D - 0.15, 0.75D - 0.05, 0.5D - 0.05, 0.70D + 0.28, 0.75D + 0.05, 0.5D + 0.05 ); + super.renderInventory( blk, is, renderer ); + + renderer.renderAllFaces = false; + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + return true; + } + + @Override + public void renderTile(AEBaseBlock blk, AEBaseTile tile, Tessellator tess, double x, double y, double z, float f, RenderBlocks rbinstance) + { + TileCrank tc = (TileCrank) tile; + if ( tc.getUp() == null || tc.getUp() == ForgeDirection.UNKNOWN ) + return; + + Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.locationBlocksTexture ); + RenderHelper.disableStandardItemLighting(); + + if ( Minecraft.isAmbientOcclusionEnabled() ) + GL11.glShadeModel( GL11.GL_SMOOTH ); + else + GL11.glShadeModel( GL11.GL_FLAT ); + + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + + applyTESRRotation( x, y, z, tile.getForward(), tile.getUp() ); + + GL11.glTranslated( 0.5, 0, 0.5 ); + GL11.glRotatef( tc.visibleRotation, 0, 1, 0 ); + GL11.glTranslated( -0.5, 0, -0.5 ); + + tess.setTranslation( -tc.xCoord, -tc.yCoord, -tc.zCoord ); + tess.startDrawingQuads(); + rbinstance.renderAllFaces = true; + rbinstance.blockAccess = tc.worldObj; + + rbinstance.setRenderBounds( 0.5D - 0.05, 0.5D - 0.5, 0.5D - 0.05, 0.5D + 0.05, 0.5D + 0.1, 0.5D + 0.05 ); + + rbinstance.renderStandardBlock( blk, tc.xCoord, tc.yCoord, tc.zCoord ); + + rbinstance.setRenderBounds( 0.70D - 0.15, 0.55D - 0.05, 0.5D - 0.05, 0.70D + 0.15, 0.55D + 0.05, 0.5D + 0.05 ); + + rbinstance.renderStandardBlock( blk, tc.xCoord, tc.yCoord, tc.zCoord ); + + tess.draw(); + tess.setTranslation( 0, 0, 0 ); + RenderHelper.enableStandardItemLighting(); + } + +} diff --git a/client/render/blocks/RenderBlockEnergyCube.java b/client/render/blocks/RenderBlockEnergyCube.java new file mode 100644 index 00000000..f56e0b5f --- /dev/null +++ b/client/render/blocks/RenderBlockEnergyCube.java @@ -0,0 +1,47 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.api.implementations.IAEItemPowerStorage; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; + +public class RenderBlockEnergyCube extends BaseBlockRender +{ + + public RenderBlockEnergyCube() { + super( false, 20 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + IAEItemPowerStorage myItem = (IAEItemPowerStorage) is.getItem(); + double internalCurrentPower = myItem.getAECurrentPower( is ); + double internalMaxPower = myItem.getAEMaxPower( is ); + + int meta = (int) (8.0 * (internalCurrentPower / internalMaxPower)); + + if ( meta > 7 ) + meta = 7; + if ( meta < 0 ) + meta = 0; + + renderer.setOverrideBlockTexture( blk.getIcon( 0, meta ) ); + super.renderInventory( blk, is, renderer ); + renderer.setOverrideBlockTexture( null ); + } + + @Override + public boolean renderInWorld(AEBaseBlock blk, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + int meta = world.getBlockMetadata( x, y, z ); + + renderer.overrideBlockTexture = blk.getIcon( 0, meta ); + boolean out = renderer.renderStandardBlock( blk, x, y, z ); + renderer.overrideBlockTexture = null; + + return out; + } +} diff --git a/client/render/blocks/RenderBlockWireless.java b/client/render/blocks/RenderBlockWireless.java new file mode 100644 index 00000000..5d18041c --- /dev/null +++ b/client/render/blocks/RenderBlockWireless.java @@ -0,0 +1,247 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.AEColor; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.BlockRenderInfo; +import appeng.client.texture.CableBusTextures; +import appeng.client.texture.ExtraTextures; +import appeng.client.texture.OffsetIcon; +import appeng.tile.networking.TileWireless; +import appeng.util.Platform; + +public class RenderBlockWireless extends BaseBlockRender +{ + + public RenderBlockWireless() { + super( false, 20 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + this.blk = blk; + cenx = 0; + ceny = 0; + cenz = 0; + hasChan = false; + hasPower = false; + BlockRenderInfo ri = blk.getRendererInstance(); + Tessellator tess = Tessellator.instance; + + renderer.renderAllFaces = true; + + Icon r = CableBusTextures.PartMonitorSidesStatus.getIcon(); + ri.setTemporaryRenderIcons( r, r, CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), r, r ); + renderBlockBounds( renderer, 5, 5, 0, 11, 11, 1, ForgeDirection.EAST, ForgeDirection.UP, ForgeDirection.SOUTH ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + r = CableBusTextures.PartMonitorSides.getIcon(); + ri.setTemporaryRenderIcons( r, r, ExtraTextures.BlockChargerInside.getIcon(), ExtraTextures.BlockChargerInside.getIcon(), r, r ); + renderBlockBounds( renderer, 5, 5, 1, 11, 11, 2, ForgeDirection.EAST, ForgeDirection.UP, ForgeDirection.SOUTH ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + tess.startDrawingQuads(); + ri.setTemporaryRenderIcon( null ); + renderTorchAtAngle( renderer, ForgeDirection.EAST, ForgeDirection.UP, ForgeDirection.SOUTH ); + super.postRenderInWorld( renderer ); + tess.draw(); + + ri.setTemporaryRenderIcons( r, r, ExtraTextures.BlockChargerInside.getIcon(), ExtraTextures.BlockChargerInside.getIcon(), r, r ); + + ForgeDirection sides[] = new ForgeDirection[] { ForgeDirection.EAST, ForgeDirection.WEST, ForgeDirection.UP, ForgeDirection.DOWN }; + + int s = 1; + + for (ForgeDirection side : sides) + { + renderBlockBounds( renderer, 8 + (side.offsetX != 0 ? side.offsetX * 2 : -2), 8 + (side.offsetY != 0 ? side.offsetY * 2 : -2), 2 + + (side.offsetZ != 0 ? side.offsetZ * 2 : -1) + s, 8 + (side.offsetX != 0 ? side.offsetX * 4 : 2), + 8 + (side.offsetY != 0 ? side.offsetY * 4 : 2), 2 + (side.offsetZ != 0 ? side.offsetZ * 5 : 1) + s, ForgeDirection.EAST, ForgeDirection.UP, + ForgeDirection.SOUTH ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + } + + s = 3; + for (ForgeDirection side : sides) + { + renderBlockBounds( renderer, 8 + (side.offsetX != 0 ? side.offsetX * 4 : -1), 8 + (side.offsetY != 0 ? side.offsetY * 4 : -1), 1 + + (side.offsetZ != 0 ? side.offsetZ * 4 : -1) + s, 8 + (side.offsetX != 0 ? side.offsetX * 5 : 1), + 8 + (side.offsetY != 0 ? side.offsetY * 5 : 1), 2 + (side.offsetZ != 0 ? side.offsetZ * 5 : 1) + s, ForgeDirection.EAST, ForgeDirection.UP, + ForgeDirection.SOUTH ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + } + } + + int cenx = 0; + int ceny = 0; + int cenz = 0; + AEBaseBlock blk; + boolean hasChan = false; + boolean hasPower = false; + + @Override + public boolean renderInWorld(AEBaseBlock blk, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + TileWireless tw = blk.getTileEntity( world, x, y, z ); + this.blk = blk; + if ( tw != null ) + { + hasChan = (tw.clientFlags & (TileWireless.POWERED_FLAG | TileWireless.CHANNEL_FLAG)) == (TileWireless.POWERED_FLAG | TileWireless.CHANNEL_FLAG); + hasPower = (tw.clientFlags & TileWireless.POWERED_FLAG) == TileWireless.POWERED_FLAG; + + BlockRenderInfo ri = blk.getRendererInstance(); + + ForgeDirection fdy = tw.getUp(); + ForgeDirection fdz = tw.getForward(); + ForgeDirection fdx = Platform.crossProduct( fdz, fdy ).getOpposite(); + + renderer.renderAllFaces = true; + + Icon r = CableBusTextures.PartMonitorSidesStatus.getIcon(); + ri.setTemporaryRenderIcons( r, r, CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), r, r ); + renderBlockBounds( renderer, 5, 5, 0, 11, 11, 1, fdx, fdy, fdz ); + super.renderInWorld( blk, world, x, y, z, renderer ); + + r = CableBusTextures.PartMonitorSides.getIcon(); + ri.setTemporaryRenderIcons( r, r, ExtraTextures.BlockChargerInside.getIcon(), ExtraTextures.BlockChargerInside.getIcon(), r, r ); + renderBlockBounds( renderer, 5, 5, 1, 11, 11, 2, fdx, fdy, fdz ); + super.renderInWorld( blk, world, x, y, z, renderer ); + + cenx = x; + ceny = y; + cenz = z; + ri.setTemporaryRenderIcon( null ); + + renderTorchAtAngle( renderer, fdx, fdy, fdz ); + super.postRenderInWorld( renderer ); + + ri.setTemporaryRenderIcons( r, r, ExtraTextures.BlockChargerInside.getIcon(), ExtraTextures.BlockChargerInside.getIcon(), r, r ); + + ForgeDirection sides[] = new ForgeDirection[] { ForgeDirection.EAST, ForgeDirection.WEST, ForgeDirection.UP, ForgeDirection.DOWN }; + + int s = 1; + + for (ForgeDirection side : sides) + { + renderBlockBounds( renderer, 8 + (side.offsetX != 0 ? side.offsetX * 2 : -2), 8 + (side.offsetY != 0 ? side.offsetY * 2 : -2), 2 + + (side.offsetZ != 0 ? side.offsetZ * 2 : -1) + s, 8 + (side.offsetX != 0 ? side.offsetX * 4 : 2), + 8 + (side.offsetY != 0 ? side.offsetY * 4 : 2), 2 + (side.offsetZ != 0 ? side.offsetZ * 5 : 1) + s, fdx, fdy, fdz ); + super.renderInWorld( blk, world, x, y, z, renderer ); + } + + s = 3; + for (ForgeDirection side : sides) + { + renderBlockBounds( renderer, 8 + (side.offsetX != 0 ? side.offsetX * 4 : -1), 8 + (side.offsetY != 0 ? side.offsetY * 4 : -1), 1 + + (side.offsetZ != 0 ? side.offsetZ * 4 : -1) + s, 8 + (side.offsetX != 0 ? side.offsetX * 5 : 1), + 8 + (side.offsetY != 0 ? side.offsetY * 5 : 1), 2 + (side.offsetZ != 0 ? side.offsetZ * 5 : 1) + s, fdx, fdy, fdz ); + super.renderInWorld( blk, world, x, y, z, renderer ); + } + + r = CableBusTextures.PartMonitorSidesStatusLights.getIcon(); + // ri.setTemporaryRenderIcons( r, r, ExtraTextures.BlockChargerInside.getIcon(), + // ExtraTextures.BlockChargerInside.getIcon(), r, r ); + renderBlockBounds( renderer, 5, 5, 0, 11, 11, 1, fdx, fdy, fdz ); + + if ( hasChan ) + { + int l = 14; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( AEColor.Transparent.blackVariant ); + } + else if ( hasPower ) + { + int l = 9; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( AEColor.Transparent.whiteVariant ); + } + else + { + Tessellator.instance.setBrightness( 0 ); + Tessellator.instance.setColorOpaque_I( 0x000000 ); + } + + if ( ForgeDirection.UP != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.UP ); + if ( ForgeDirection.DOWN != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.DOWN ); + if ( ForgeDirection.EAST != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.EAST ); + if ( ForgeDirection.WEST != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.WEST ); + if ( ForgeDirection.SOUTH != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.SOUTH ); + if ( ForgeDirection.NORTH != fdz.getOpposite() ) + super.renderFace( x, y, z, blk, r, renderer, ForgeDirection.NORTH ); + + ri.setTemporaryRenderIcon( null ); + renderer.renderAllFaces = false; + } + + return true; + } + + private void renderTorchAtAngle(RenderBlocks renderer, ForgeDirection x, ForgeDirection y, ForgeDirection z) + { + Icon r = (hasChan ? CableBusTextures.BlockWirelessOn.getIcon() : blk.getIcon( 0, 0 )); + Icon sides = new OffsetIcon( r, 0.0f, -2.0f ); + + switch (z) + { + case DOWN: + renderer.uvRotateNorth = 3; + renderer.uvRotateSouth = 3; + renderer.uvRotateEast = 3; + renderer.uvRotateWest = 3; + break; + case EAST: + renderer.uvRotateTop = 1; + renderer.uvRotateBottom = 2; + renderer.uvRotateEast = 2; + renderer.uvRotateWest = 1; + break; + case NORTH: + renderer.uvRotateTop = 0; + renderer.uvRotateBottom = 0; + renderer.uvRotateNorth = 2; + renderer.uvRotateSouth = 1; + break; + case SOUTH: + renderer.uvRotateTop = 3; + renderer.uvRotateBottom = 3; + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 2; + break; + case WEST: + renderer.uvRotateTop = 2; + renderer.uvRotateBottom = 1; + renderer.uvRotateEast = 1; + renderer.uvRotateWest = 2; + break; + default: + break; + } + + Tessellator.instance.setColorOpaque_I( 0xffffff ); + renderBlockBounds( renderer, 0, 7, 1, 16, 9, 16, x, y, z ); + renderFace( cenx, ceny, cenz, blk, sides, renderer, y ); + renderFace( cenx, ceny, cenz, blk, sides, renderer, y.getOpposite() ); + + renderBlockBounds( renderer, 7, 0, 1, 9, 16, 16, x, y, z ); + renderFace( cenx, ceny, cenz, blk, sides, renderer, x ); + renderFace( cenx, ceny, cenz, blk, sides, renderer, x.getOpposite() ); + + renderBlockBounds( renderer, 7, 7, 1, 9, 9, 10.6, x, y, z ); + renderFace( cenx, ceny, cenz, blk, r, renderer, z ); + } +} diff --git a/client/render/blocks/RenderCable.java b/client/render/blocks/RenderCable.java new file mode 100644 index 00000000..ed8ed6eb --- /dev/null +++ b/client/render/blocks/RenderCable.java @@ -0,0 +1,62 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; + +public class RenderCable extends BaseBlockRender +{ + + public void renderCableAt(double Thickness, IBlockAccess world, int x, int y, int z, AEBaseBlock block, RenderBlocks renderer, Icon texture, double pull, + EnumSet connections) + { + + if ( connections.contains( ForgeDirection.UNKNOWN ) ) + { + renderer.setRenderBounds( 0.5D - Thickness, 0.5D - Thickness, 0.5D - Thickness, 0.5D + Thickness, 0.5D + Thickness, 0.5D + Thickness ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.WEST ) ) + { + renderer.setRenderBounds( 0.0D, 0.5D - Thickness, 0.5D - Thickness, 0.5D - Thickness - pull, 0.5D + Thickness, 0.5D + Thickness ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.EAST ) ) + { + renderer.setRenderBounds( 0.5D + Thickness + pull, 0.5D - Thickness, 0.5D - Thickness, 1.0D, 0.5D + Thickness, 0.5D + Thickness ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.NORTH ) ) + { + renderer.setRenderBounds( 0.5D - Thickness, 0.5D - Thickness, 0.0D, 0.5D + Thickness, 0.5D + Thickness, 0.5D - Thickness - pull ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.SOUTH ) ) + { + renderer.setRenderBounds( 0.5D - Thickness, 0.5D - Thickness, 0.5D + Thickness + pull, 0.5D + Thickness, 0.5D + Thickness, 1.0D ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.DOWN ) ) + { + renderer.setRenderBounds( 0.5D - Thickness, 0.0D, 0.5D - Thickness, 0.5D + Thickness, 0.5D - Thickness - pull, 0.5D + Thickness ); + renderer.renderStandardBlock( block, x, y, z ); + } + + if ( connections.contains( ForgeDirection.UP ) ) + { + renderer.setRenderBounds( 0.5D - Thickness, 0.5D + Thickness + pull, 0.5D - Thickness, 0.5D + Thickness, 1.0D, 0.5D + Thickness ); + renderer.renderStandardBlock( block, x, y, z ); + } + + } +} diff --git a/client/render/blocks/RenderDrive.java b/client/render/blocks/RenderDrive.java new file mode 100644 index 00000000..f4f778dd --- /dev/null +++ b/client/render/blocks/RenderDrive.java @@ -0,0 +1,308 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; +import appeng.tile.storage.TileDrive; +import appeng.util.Platform; + +public class RenderDrive extends BaseBlockRender +{ + + public RenderDrive() { + super( false, 0 ); + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + renderer.overrideBlockTexture = ExtraTextures.getMissing(); + this.renderInvBlock( EnumSet.of( ForgeDirection.SOUTH ), block, Tessellator.instance, 0x000000, renderer ); + + renderer.overrideBlockTexture = null; + super.renderInventory( block, is, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + TileDrive sp = imb.getTileEntity( world, x, y, z ); + renderer.setRenderBounds( 0, 0, 0, 1, 1, 1 ); + + ForgeDirection up = sp.getUp(); + ForgeDirection forward = sp.getForward(); + ForgeDirection west = Platform.crossProduct( forward, up ); + + boolean result = super.renderInWorld( imb, world, x, y, z, renderer ); + Tessellator tess = Tessellator.instance; + + Icon ico = ExtraTextures.MEStorageCellTextures.getIcon(); + + int b = world.getLightBrightnessForSkyBlocks( x + forward.offsetX, y + forward.offsetY, z + forward.offsetZ, 0 ); + + for (int yy = 0; yy < 5; yy++) + { + for (int xx = 0; xx < 2; xx++) + { + int stat = sp.getCellStatus( yy * 2 + (1 - xx) ); + selectFace( renderer, west, up, forward, 2 + xx * 7, 7 + xx * 7, 1 + yy * 3, 3 + yy * 3 ); + + int spin = 0; + + switch (forward.offsetX + forward.offsetY * 2 + forward.offsetZ * 3) + { + case 1: + switch (up) + { + case UP: + spin = 3; + break; + case DOWN: + spin = 1; + break; + case NORTH: + spin = 0; + break; + case SOUTH: + spin = 2; + break; + default: + } + break; + case -1: + switch (up) + { + case UP: + spin = 1; + break; + case DOWN: + spin = 3; + break; + case NORTH: + spin = 0; + break; + case SOUTH: + spin = 2; + break; + default: + } + break; + case -2: + switch (up) + { + case EAST: + spin = 1; + break; + case WEST: + spin = 3; + break; + case NORTH: + spin = 2; + break; + case SOUTH: + spin = 0; + break; + default: + } + break; + case 2: + switch (up) + { + case EAST: + spin = 1; + break; + case WEST: + spin = 3; + break; + case NORTH: + spin = 0; + break; + case SOUTH: + spin = 0; + break; + default: + } + break; + case 3: + switch (up) + { + case UP: + spin = 2; + break; + case DOWN: + spin = 0; + break; + case EAST: + spin = 3; + break; + case WEST: + spin = 1; + break; + default: + } + break; + case -3: + switch (up) + { + case UP: + spin = 2; + break; + case DOWN: + spin = 0; + break; + case EAST: + spin = 1; + break; + case WEST: + spin = 3; + break; + default: + } + break; + } + + double u1 = ico.getInterpolatedU( (spin % 4 < 2) ? 1 : 6 ); + double u2 = ico.getInterpolatedU( ((spin + 1) % 4 < 2) ? 1 : 6 ); + double u3 = ico.getInterpolatedU( ((spin + 2) % 4 < 2) ? 1 : 6 ); + double u4 = ico.getInterpolatedU( ((spin + 3) % 4 < 2) ? 1 : 6 ); + + int m = 1; + int mx = 3; + if ( stat == 0 ) + { + m = 4; + mx = 5; + } + + double v1 = ico.getInterpolatedV( ((spin + 1) % 4 < 2) ? m : mx ); + double v2 = ico.getInterpolatedV( ((spin + 2) % 4 < 2) ? m : mx ); + double v3 = ico.getInterpolatedV( ((spin + 3) % 4 < 2) ? m : mx ); + double v4 = ico.getInterpolatedV( ((spin + 0) % 4 < 2) ? m : mx ); + + tess.setBrightness( b ); + tess.setColorOpaque_I( 0xffffff ); + switch (forward.offsetX + forward.offsetY * 2 + forward.offsetZ * 3) + { + case 1: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMinZ, u4, v4 ); + break; + case -1: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case -2: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case 2: + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case 3: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMinY, z + renderer.renderMaxZ, u4, v4 ); + break; + case -3: + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMinY, z + renderer.renderMaxZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u4, v4 ); + break; + } + + if ( (forward == ForgeDirection.UP && up == ForgeDirection.SOUTH) || forward == ForgeDirection.DOWN ) + selectFace( renderer, west, up, forward, 3 + xx * 7, 4 + xx * 7, 1 + yy * 3, 2 + yy * 3 ); + else + selectFace( renderer, west, up, forward, 5 + xx * 7, 6 + xx * 7, 2 + yy * 3, 3 + yy * 3 ); + + if ( stat != 0 ) + { + Icon wico = ExtraTextures.White.getIcon(); + u1 = wico.getInterpolatedU( (spin % 4 < 2) ? 1 : 6 ); + u2 = wico.getInterpolatedU( ((spin + 1) % 4 < 2) ? 1 : 6 ); + u3 = wico.getInterpolatedU( ((spin + 2) % 4 < 2) ? 1 : 6 ); + u4 = wico.getInterpolatedU( ((spin + 3) % 4 < 2) ? 1 : 6 ); + + v1 = wico.getInterpolatedV( ((spin + 1) % 4 < 2) ? 1 : 3 ); + v2 = wico.getInterpolatedV( ((spin + 2) % 4 < 2) ? 1 : 3 ); + v3 = wico.getInterpolatedV( ((spin + 3) % 4 < 2) ? 1 : 3 ); + v4 = wico.getInterpolatedV( ((spin + 0) % 4 < 2) ? 1 : 3 ); + + if ( sp.isPowered() ) + tess.setBrightness( 15 << 20 | 15 << 4 ); + else + tess.setBrightness( 0 ); + + if ( stat == 1 ) + Tessellator.instance.setColorOpaque_I( 0x00ff00 ); + if ( stat == 2 ) + Tessellator.instance.setColorOpaque_I( 0xffaa00 ); + if ( stat == 3 ) + Tessellator.instance.setColorOpaque_I( 0xff0000 ); + + switch (forward.offsetX + forward.offsetY * 2 + forward.offsetZ * 3) + { + case 1: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMinZ, u4, v4 ); + break; + case -1: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case -2: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case 2: + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMinZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMinZ, u4, v4 ); + break; + case 3: + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMinY, z + renderer.renderMaxZ, u4, v4 ); + break; + case -3: + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMinY, z + renderer.renderMaxZ, u1, v1 ); + tess.addVertexWithUV( x + renderer.renderMinX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u2, v2 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMaxY, z + renderer.renderMaxZ, u3, v3 ); + tess.addVertexWithUV( x + renderer.renderMaxX, y + renderer.renderMinY, z + renderer.renderMaxZ, u4, v4 ); + break; + } + } + } + } + + renderer.overrideBlockTexture = null; + return result; + } +} diff --git a/client/render/blocks/RenderMEChest.java b/client/render/blocks/RenderMEChest.java new file mode 100644 index 00000000..7d1971b9 --- /dev/null +++ b/client/render/blocks/RenderMEChest.java @@ -0,0 +1,119 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.storage.ICellHandler; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; +import appeng.client.texture.FlipableIcon; +import appeng.client.texture.OffsetIcon; +import appeng.tile.storage.TileChest; +import appeng.util.Platform; + +public class RenderMEChest extends BaseBlockRender +{ + + public RenderMEChest() { + super( false, 0 ); + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + renderer.overrideBlockTexture = ExtraTextures.getMissing(); + this.renderInvBlock( EnumSet.of( ForgeDirection.SOUTH ), block, Tessellator.instance, 0x000000, renderer ); + + renderer.overrideBlockTexture = ExtraTextures.MEChest.getIcon(); + this.renderInvBlock( EnumSet.of( ForgeDirection.UP ), block, Tessellator.instance, 0xffffff, renderer ); + + renderer.overrideBlockTexture = null; + super.renderInventory( block, is, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + TileChest sp = imb.getTileEntity( world, x, y, z ); + renderer.setRenderBounds( 0, 0, 0, 1, 1, 1 ); + + ForgeDirection up = sp.getUp(); + ForgeDirection forward = sp.getForward(); + ForgeDirection west = Platform.crossProduct( forward, up ); + + preRenderInWorld( imb, world, x, y, z, renderer ); + + int stat = sp.getCellStatus( 0 ); + boolean result = renderer.renderStandardBlock( imb, x, y, z ); + + selectFace( renderer, west, up, forward, 5, 16 - 5, 9, 12 ); + + int offsetU = -4; + int offsetV = 8; + if ( stat == 0 ) + offsetV = 3; + + int b = world.getLightBrightnessForSkyBlocks( x + forward.offsetX, y + forward.offsetY, z + forward.offsetZ, 0 ); + Tessellator.instance.setBrightness( b ); + Tessellator.instance.setColorOpaque_I( 0xffffff ); + + FlipableIcon fico = new FlipableIcon( new OffsetIcon( ExtraTextures.MEStorageCellTextures.getIcon(), offsetU, offsetV ) ); + if ( forward == ForgeDirection.EAST && (up == ForgeDirection.NORTH || up == ForgeDirection.SOUTH) ) + fico.setFlip( true, false ); + else if ( forward == ForgeDirection.NORTH && up == ForgeDirection.EAST ) + fico.setFlip( false, true ); + else if ( forward == ForgeDirection.NORTH && up == ForgeDirection.WEST ) + fico.setFlip( true, false ); + else if ( forward == ForgeDirection.DOWN && up == ForgeDirection.EAST ) + fico.setFlip( false, true ); + else if ( forward == ForgeDirection.DOWN ) + fico.setFlip( true, false ); + + renderFace( x, y, z, imb, fico, renderer, forward ); + + if ( stat != 0 ) + { + b = 0; + if ( sp.isPowered() ) + { + b = 15 << 20 | 15 << 4; + } + + Tessellator.instance.setBrightness( b ); + if ( stat == 1 ) + Tessellator.instance.setColorOpaque_I( 0x00ff00 ); + if ( stat == 2 ) + Tessellator.instance.setColorOpaque_I( 0xffaa00 ); + if ( stat == 3 ) + Tessellator.instance.setColorOpaque_I( 0xff0000 ); + selectFace( renderer, west, up, forward, 9, 10, 11, 12 ); + renderFace( x, y, z, imb, ExtraTextures.White.getIcon(), renderer, forward ); + } + + b = world.getLightBrightnessForSkyBlocks( x + up.offsetX, y + up.offsetY, z + up.offsetZ, 0 ); + if ( sp.isPowered() ) + { + b = 15 << 20 | 15 << 4; + } + + Tessellator.instance.setBrightness( b ); + Tessellator.instance.setColorOpaque_I( 0xffffff ); + renderer.setRenderBounds( 0, 0, 0, 1, 1, 1 ); + + ICellHandler ch = AEApi.instance().registries().cell().getHander( sp.getStorageType() ); + Icon ico = ch == null ? null : ch.getTopTexture(); + renderFace( x, y, z, imb, ico == null ? ExtraTextures.MEChest.getIcon() : ico, renderer, up ); + + renderer.overrideBlockTexture = null; + postRenderInWorld( renderer ); + + return result; + } +} diff --git a/client/render/blocks/RenderNull.java b/client/render/blocks/RenderNull.java new file mode 100644 index 00000000..9737df1a --- /dev/null +++ b/client/render/blocks/RenderNull.java @@ -0,0 +1,28 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; + +public class RenderNull extends BaseBlockRender +{ + + public RenderNull() { + super( false, 20 ); + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + return true; + } + +} diff --git a/client/render/blocks/RenderQNB.java b/client/render/blocks/RenderQNB.java new file mode 100644 index 00000000..02c48821 --- /dev/null +++ b/client/render/blocks/RenderQNB.java @@ -0,0 +1,122 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.block.AEBaseBlock; +import appeng.client.texture.ExtraTextures; +import appeng.tile.qnb.TileQuantumBridge; + +public class RenderQNB extends RenderCable +{ + + @Override + public void renderInventory(AEBaseBlock block, ItemStack item, RenderBlocks renderer) + { + float px = 2.0f / 16.0f; + float maxpx = 14.0f / 16.0f; + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + + super.renderInventory( block, item, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + TileQuantumBridge tqb = block.getTileEntity( world, x, y, z ); + if ( tqb == null ) + return false; + + renderer.renderAllFaces = true; + + if ( tqb.getBlockType() == AEApi.instance().blocks().blockQuantumLink.block() ) + { + if ( tqb.isFormed() ) + { + EnumSet sides = EnumSet.allOf( ForgeDirection.class ); + renderCableAt( 0.11D, world, x, y, z, block, renderer, block.getIcon( 0, 0 ), 0.141D, sides ); + renderCableAt( 0.188D, world, x, y, z, block, renderer, block.getIcon( 0, 0 ), 0.1875D, + EnumSet.complementOf( EnumSet.of( ForgeDirection.UNKNOWN ) ) ); + } + + float px = 2.0f / 16.0f; + float maxpx = 14.0f / 16.0f; + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + renderer.renderStandardBlock( block, x, y, z ); + // super.renderWorldBlock(world, x, y, z, block, modelId, renderer); + } + else + { + if ( !tqb.isFormed() ) + { + float px = 2.0f / 16.0f; + float maxpx = 14.0f / 16.0f; + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + renderer.renderStandardBlock( block, x, y, z ); + } + else if ( tqb.isCorner() ) + { + // renderCableAt(0.11D, world, x, y, z, block, modelId, renderer, + // AppEngTextureRegistry.Blocks.MECable.get(), true, 0.0D); + renderCableAt( 0.188D, world, x, y, z, block, renderer, ExtraTextures.BlockInterfaceAlternate.getIcon(), 0.05D, + EnumSet.complementOf( EnumSet.of( ForgeDirection.UNKNOWN ) ) ); + + float px = 4.0f / 16.0f; + float maxpx = 12.0f / 16.0f; + + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + renderer.renderStandardBlock( block, x, y, z ); + + if ( tqb.isPowered() ) + { + + px = 3.9f / 16.0f; + maxpx = 12.1f / 16.0f; + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + + int bn = 15; + Tessellator.instance.setColorOpaque_F( 1.0F, 1.0F, 1.0F ); + Tessellator.instance.setBrightness( bn << 20 | bn << 4 ); + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + renderFace( x, y, z, block, block.getIcon( 0, 0 ), renderer, side ); + + } + } + else + { + float px = 2.0f / 16.0f; + float maxpx = 14.0f / 16.0f; + renderer.setRenderBounds( 0, px, px, 1, maxpx, maxpx ); + renderer.renderStandardBlock( block, x, y, z ); + + renderer.setRenderBounds( px, 0, px, maxpx, 1, maxpx ); + renderer.renderStandardBlock( block, x, y, z ); + + renderer.setRenderBounds( px, px, 0, maxpx, maxpx, 1 ); + renderer.renderStandardBlock( block, x, y, z ); + + if ( tqb.isPowered() ) + { + px = -0.01f / 16.0f; + maxpx = 16.01f / 16.0f; + renderer.setRenderBounds( px, px, px, maxpx, maxpx, maxpx ); + + int bn = 15; + Tessellator.instance.setColorOpaque_F( 1.0F, 1.0F, 1.0F ); + Tessellator.instance.setBrightness( bn << 20 | bn << 4 ); + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + renderFace( x, y, z, block, block.getIcon( 0, 0 ), renderer, side ); + } + } + } + + renderer.renderAllFaces = false; + return true; + } + +} diff --git a/client/render/blocks/RenderQuartzGlass.java b/client/render/blocks/RenderQuartzGlass.java new file mode 100644 index 00000000..6500eda7 --- /dev/null +++ b/client/render/blocks/RenderQuartzGlass.java @@ -0,0 +1,153 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; + +public class RenderQuartzGlass extends BaseBlockRender +{ + + public RenderQuartzGlass() { + super( false, 0 ); + } + + boolean isFlush(AEBaseBlock imb, IBlockAccess world, int x, int y, int z) + { + return isGlass( imb, world, x, y, z ); + } + + boolean isGlass(AEBaseBlock imb, IBlockAccess world, int x, int y, int z) + { + return world.getBlockId( x, y, z ) == AEApi.instance().blocks().blockQuartzGlass.block().blockID + || world.getBlockId( x, y, z ) == AEApi.instance().blocks().blockQuartzVibrantGlass.block().blockID; + } + + void renderEdge(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer, ForgeDirection side, ForgeDirection direction) + { + if ( !isFlush( imb, world, x + side.offsetX, y + side.offsetY, z + side.offsetZ ) ) + { + if ( !isFlush( imb, world, x + direction.offsetX, y + direction.offsetY, z + direction.offsetZ ) ) + { + float minX = 0.5f + (side.offsetX + direction.offsetX) / 2.0f; + float minY = 0.5f + (side.offsetY + direction.offsetY) / 2.0f; + float minZ = 0.5f + (side.offsetZ + direction.offsetZ) / 2.0f; + float maxX = 0.5f + (side.offsetX + direction.offsetX) / 2.0f; + float maxY = 0.5f + (side.offsetY + direction.offsetY) / 2.0f; + float maxZ = 0.5f + (side.offsetZ + direction.offsetZ) / 2.0f; + + if ( 0 == side.offsetX && 0 == direction.offsetX ) + { + minX = 0.0f; + maxX = 1.0f; + } + if ( 0 == side.offsetY && 0 == direction.offsetY ) + { + minY = 0.0f; + maxY = 1.0f; + } + if ( 0 == side.offsetZ && 0 == direction.offsetZ ) + { + minZ = 0.0f; + maxZ = 1.0f; + } + + if ( maxX <= 0.001f ) + maxX += 0.9f / 16.0f; + if ( maxY <= 0.001f ) + maxY += 0.9f / 16.0f; + if ( maxZ <= 0.001f ) + maxZ += 0.9f / 16.0f; + + if ( minX >= 0.999f ) + minX -= 0.9f / 16.0f; + if ( minY >= 0.999f ) + minY -= 0.9f / 16.0f; + if ( minZ >= 0.999f ) + minZ -= 0.9f / 16.0f; + + renderer.setRenderBounds( minX, minY, minZ, maxX, maxY, maxZ ); + + switch (side) + { + case WEST: + renderer.renderFaceXNeg( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + case EAST: + renderer.renderFaceXPos( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + case NORTH: + renderer.renderFaceZNeg( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + case SOUTH: + renderer.renderFaceZPos( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + case DOWN: + renderer.renderFaceYNeg( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + case UP: + renderer.renderFaceYPos( imb, x, y, z, ExtraTextures.GlassFrame.getIcon() ); + break; + default: + break; + } + } + } + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + renderer.overrideBlockTexture = ExtraTextures.GlassFrame.getIcon(); + super.renderInventory( block, is, renderer ); + renderer.overrideBlockTexture = null; + super.renderInventory( block, is, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + renderer.setRenderBounds( 0, 0, 0, 1, 1, 1 ); + + renderer.overrideBlockTexture = imb.getIcon( 0, 0 ); + boolean result = renderer.renderStandardBlock( imb, x, y, z ); + + renderer.overrideBlockTexture = null; + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.UP, ForgeDirection.EAST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.UP, ForgeDirection.WEST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.UP, ForgeDirection.NORTH ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.UP, ForgeDirection.SOUTH ); + + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.DOWN, ForgeDirection.EAST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.DOWN, ForgeDirection.WEST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.DOWN, ForgeDirection.NORTH ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.DOWN, ForgeDirection.SOUTH ); + + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.EAST, ForgeDirection.UP ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.EAST, ForgeDirection.DOWN ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.EAST, ForgeDirection.NORTH ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.EAST, ForgeDirection.SOUTH ); + + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.WEST, ForgeDirection.UP ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.WEST, ForgeDirection.DOWN ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.WEST, ForgeDirection.NORTH ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.WEST, ForgeDirection.SOUTH ); + + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.NORTH, ForgeDirection.EAST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.NORTH, ForgeDirection.WEST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.NORTH, ForgeDirection.UP ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.NORTH, ForgeDirection.DOWN ); + + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.SOUTH, ForgeDirection.EAST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.SOUTH, ForgeDirection.WEST ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.SOUTH, ForgeDirection.UP ); + renderEdge( imb, world, x, y, z, renderer, ForgeDirection.SOUTH, ForgeDirection.DOWN ); + + return result; + } + +} diff --git a/client/render/blocks/RenderQuartzOre.java b/client/render/blocks/RenderQuartzOre.java new file mode 100644 index 00000000..f956dfcb --- /dev/null +++ b/client/render/blocks/RenderQuartzOre.java @@ -0,0 +1,41 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.block.solids.OreQuartz; +import appeng.client.render.BaseBlockRender; +import appeng.client.texture.ExtraTextures; + +public class RenderQuartzOre extends BaseBlockRender +{ + + public RenderQuartzOre() { + super( false, 20 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + super.renderInventory( blk, is, renderer ); + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.OreQuartzStone.getIcon() ); + super.renderInventory( blk, is, renderer ); + blk.getRendererInstance().setTemporaryRenderIcon( null ); + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + OreQuartz blk = (OreQuartz) block; + blk.enhanceBrightness = true; + super.renderInWorld( block, world, x, y, z, renderer ); + blk.enhanceBrightness = false; + + blk.getRendererInstance().setTemporaryRenderIcon( ExtraTextures.OreQuartzStone.getIcon() ); + boolean out = super.renderInWorld( block, world, x, y, z, renderer ); + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + return out; + } +} diff --git a/client/render/blocks/RenderQuartzTorch.java b/client/render/blocks/RenderQuartzTorch.java new file mode 100644 index 00000000..c14b03e7 --- /dev/null +++ b/client/render/blocks/RenderQuartzTorch.java @@ -0,0 +1,192 @@ +package appeng.client.render.blocks; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.IOrientable; +import appeng.block.AEBaseBlock; +import appeng.block.misc.BlockQuartzTorch; +import appeng.client.render.BaseBlockRender; + +public class RenderQuartzTorch extends BaseBlockRender +{ + + public RenderQuartzTorch() { + super( false, 20 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + Tessellator tess = Tessellator.instance; + + float Point2 = 6.0f / 16.0f; + float Point3 = 7.0f / 16.0f; + float Point13 = 10.0f / 16.0f; + float Point12 = 9.0f / 16.0f; + + float Onepx = 1.0f / 16.0f; + float rbottom = 5.0f / 16.0f; + float rtop = 10.0f / 16.0f; + + float bottom = 7.0f / 16.0f; + float top = 8.0f / 16.0f; + + float xOff = 0.0f; + float yOff = 0.0f; + float zOff = 0.0f; + + renderer.setRenderBounds( Point3 + xOff, rbottom + yOff, Point3 + zOff, Point12 + xOff, rtop + yOff, Point12 + zOff ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + renderer.setRenderBounds( Point3 + xOff, rtop + yOff, Point3 + zOff, Point3 + Onepx + xOff, rtop + Onepx + yOff, Point3 + Onepx + zOff ); + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + renderer.setRenderBounds( Point12 - Onepx + xOff, rbottom - Onepx + yOff, Point12 - Onepx + zOff, Point12 + xOff, rbottom + yOff, Point12 + zOff ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + blk.getRendererInstance().setTemporaryRenderIcon( Block.hopperBlock.getIcon( 0, 0 ) ); + renderer.renderAllFaces = true; + + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point2 + zOff, Point13 + xOff, top + yOff, Point3 + zOff ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point12 + zOff, Point13 + xOff, top + yOff, Point13 + zOff ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point3 + zOff, Point3 + xOff, top + yOff, Point12 + zOff ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + renderer.setRenderBounds( Point12 + xOff, bottom + yOff, Point3 + zOff, Point13 + xOff, top + yOff, Point12 + zOff ); + + renderInvBlock( EnumSet.allOf( ForgeDirection.class ), blk, tess, 0xffffff, renderer ); + + renderer.renderAllFaces = false; + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + BlockQuartzTorch blk = (BlockQuartzTorch) block; + + IOrientable te = getOrientable( block, world, x, y, z ); + + float Point2 = 6.0f / 16.0f; + float Point3 = 7.0f / 16.0f; + float Point13 = 10.0f / 16.0f; + float Point12 = 9.0f / 16.0f; + + float Onepx = 1.0f / 16.0f; + float rbottom = 5.0f / 16.0f; + float rtop = 10.0f / 16.0f; + + float bottom = 7.0f / 16.0f; + float top = 8.0f / 16.0f; + + float xOff = 0.0f; + float yOff = 0.0f; + float zOff = 0.0f; + + renderer.renderAllFaces = true; + if ( te != null ) + { + ForgeDirection forward = te.getUp(); + xOff = forward.offsetX * -(4.0f / 16.0f); + yOff = forward.offsetY * -(4.0f / 16.0f); + zOff = forward.offsetZ * -(4.0f / 16.0f); + } + + renderer.setRenderBounds( Point3 + xOff, rbottom + yOff, Point3 + zOff, Point12 + xOff, rtop + yOff, Point12 + zOff ); + super.renderInWorld( block, world, x, y, z, renderer ); + + int r = (x + y + z) % 2; + if ( r == 0 ) + { + renderer.setRenderBounds( Point3 + xOff, rtop + yOff, Point3 + zOff, Point3 + Onepx + xOff, rtop + Onepx + yOff, Point3 + Onepx + zOff ); + super.renderInWorld( block, world, x, y, z, renderer ); + + renderer.setRenderBounds( Point12 - Onepx + xOff, rbottom - Onepx + yOff, Point12 - Onepx + zOff, Point12 + xOff, rbottom + yOff, Point12 + zOff ); + super.renderInWorld( block, world, x, y, z, renderer ); + } + else + { + renderer.setRenderBounds( Point3 + xOff, rbottom - Onepx + yOff, Point3 + zOff, Point3 + Onepx + xOff, rbottom + yOff, Point3 + Onepx + zOff ); + super.renderInWorld( block, world, x, y, z, renderer ); + + renderer.setRenderBounds( Point12 - Onepx + xOff, rtop + yOff, Point12 - Onepx + zOff, Point12 + xOff, rtop + Onepx + yOff, Point12 + zOff ); + super.renderInWorld( block, world, x, y, z, renderer ); + } + + blk.getRendererInstance().setTemporaryRenderIcon( Block.hopperBlock.getIcon( 0, 0 ) ); + + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point2 + zOff, Point13 + xOff, top + yOff, Point3 + zOff ); + boolean out = renderer.renderStandardBlock( blk, x, y, z ); + + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point12 + zOff, Point13 + xOff, top + yOff, Point13 + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + + renderer.setRenderBounds( Point2 + xOff, bottom + yOff, Point3 + zOff, Point3 + xOff, top + yOff, Point12 + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + + renderer.setRenderBounds( Point12 + xOff, bottom + yOff, Point3 + zOff, Point13 + xOff, top + yOff, Point12 + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + + if ( te != null ) + { + ForgeDirection forward = te.getUp(); + switch (forward) + { + case EAST: + renderer.setRenderBounds( 0, bottom + yOff, bottom + zOff, Point2 + xOff, top + yOff, top + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + case WEST: + renderer.setRenderBounds( Point13 + xOff, bottom + yOff, bottom + zOff, 1.0, top + yOff, top + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + case NORTH: + renderer.setRenderBounds( bottom + xOff, bottom + yOff, Point13 + zOff, top + xOff, top + yOff, 1.0 ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + case SOUTH: + renderer.setRenderBounds( bottom + xOff, bottom + yOff, 0, top + xOff, top + yOff, Point2 + zOff ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + case UP: + renderer.setRenderBounds( Point2, 0, Point2, Point3, bottom + yOff, Point3 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point2, 0, Point12, Point3, bottom + yOff, Point13 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point12, 0, Point2, Point13, bottom + yOff, Point3 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point12, 0, Point12, Point13, bottom + yOff, Point13 ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + case DOWN: + renderer.setRenderBounds( Point2, top + yOff, Point2, Point3, 1.0, Point3 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point2, top + yOff, Point12, Point3, 1.0, Point13 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point12, top + yOff, Point2, Point13, 1.0, Point3 ); + renderer.renderStandardBlock( blk, x, y, z ); + renderer.setRenderBounds( Point12, top + yOff, Point12, Point13, 1.0, Point13 ); + renderer.renderStandardBlock( blk, x, y, z ); + break; + default: + } + } + + renderer.renderAllFaces = false; + blk.getRendererInstance().setTemporaryRenderIcon( null ); + + return out; + } +} diff --git a/client/render/blocks/RenderSpatialPylon.java b/client/render/blocks/RenderSpatialPylon.java new file mode 100644 index 00000000..8e46eaf2 --- /dev/null +++ b/client/render/blocks/RenderSpatialPylon.java @@ -0,0 +1,188 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.BlockRenderInfo; +import appeng.client.texture.ExtraTextures; +import appeng.tile.spatial.TileSpatialPylon; + +public class RenderSpatialPylon extends BaseBlockRender +{ + + public RenderSpatialPylon() { + super( false, 0 ); + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + renderer.overrideBlockTexture = ExtraTextures.BlockSpatialPylon_dim.getIcon(); + super.renderInventory( block, is, renderer ); + renderer.overrideBlockTexture = null; + super.renderInventory( block, is, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + renderer.setRenderBounds( 0, 0, 0, 1, 1, 1 ); + + TileSpatialPylon sp = imb.getTileEntity( world, x, y, z ); + + int displayBits = sp.getDisplayBits(); + ForgeDirection ori = ForgeDirection.UNKNOWN; + + if ( displayBits != 0 ) + { + if ( (displayBits & sp.DISPLAY_Z) == sp.DISPLAY_X ) + { + ori = ForgeDirection.EAST; + if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMAX ) + { + renderer.uvRotateEast = 1; + renderer.uvRotateWest = 2; + renderer.uvRotateTop = 2; + renderer.uvRotateBottom = 1; + } + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMIN ) + { + renderer.uvRotateEast = 2; + renderer.uvRotateWest = 1; + renderer.uvRotateTop = 1; + renderer.uvRotateBottom = 2; + } + else + { + renderer.uvRotateEast = 1; + renderer.uvRotateWest = 1; + renderer.uvRotateTop = 1; + renderer.uvRotateBottom = 1; + } + } + + else if ( (displayBits & sp.DISPLAY_Z) == sp.DISPLAY_Y ) + { + ori = ForgeDirection.UP; + if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMAX ) + { + renderer.uvRotateNorth = 3; + renderer.uvRotateSouth = 3; + renderer.uvRotateEast = 3; + renderer.uvRotateWest = 3; + } + } + + else if ( (displayBits & sp.DISPLAY_Z) == sp.DISPLAY_Z ) + { + ori = ForgeDirection.NORTH; + if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMAX ) + { + renderer.uvRotateSouth = 1; + renderer.uvRotateNorth = 2; + } + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMIN ) + { + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 2; + renderer.uvRotateTop = 3; + renderer.uvRotateBottom = 3; + } + else + { + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 2; + } + } + + BlockRenderInfo bri = imb.getRendererInstance(); + bri.setTemporaryRenderIcon( null ); + bri.setTemporaryRenderIcons( getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.UP ), + getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.DOWN ), + getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.SOUTH ), + getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.NORTH ), + getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.EAST ), + getBlockTextureFromSideOutside( imb, sp, displayBits, ori, ForgeDirection.WEST ) ); + + boolean r = renderer.renderStandardBlock( imb, x, y, z ); + + if ( (displayBits & sp.DISPLAY_POWEREDENABLED) == sp.DISPLAY_POWEREDENABLED ) + { + int bn = 15; + Tessellator.instance.setBrightness( bn << 20 | bn << 4 ); + Tessellator.instance.setColorOpaque_I( 0xffffff ); + + for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) + renderFace( x, y, z, imb, getBlockTextureFromSideInside( imb, sp, displayBits, ori, d ), renderer, d ); + } + else + { + bri.setTemporaryRenderIcon( null ); + bri.setTemporaryRenderIcons( getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.UP ), + getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.DOWN ), + getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.SOUTH ), + getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.NORTH ), + getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.EAST ), + getBlockTextureFromSideInside( imb, sp, displayBits, ori, ForgeDirection.WEST ) ); + + renderer.renderStandardBlock( imb, x, y, z ); + } + + bri.setTemporaryRenderIcon( null ); + renderer.uvRotateEast = renderer.uvRotateWest = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateBottom = 0; + + return r; + } + + renderer.overrideBlockTexture = imb.getIcon( 0, 0 ); + boolean result = renderer.renderStandardBlock( imb, x, y, z ); + + renderer.overrideBlockTexture = ExtraTextures.BlockSpatialPylon_dim.getIcon(); + result = renderer.renderStandardBlock( imb, x, y, z ); + + renderer.overrideBlockTexture = null; + return result; + } + + private Icon getBlockTextureFromSideOutside(AEBaseBlock blk, TileSpatialPylon sp, int displayBits, ForgeDirection ori, ForgeDirection dir) + { + + if ( ori.equals( dir ) || ori.getOpposite().equals( dir ) ) + return blk.getRendererInstance().getTexture( dir ); + + if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_MIDDLE ) + return ExtraTextures.BlockSpatialPylonC.getIcon(); + + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMIN ) + return ExtraTextures.BlockSpatialPylonE.getIcon(); + + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMAX ) + return ExtraTextures.BlockSpatialPylonE.getIcon(); + + return blk.getIcon( 0, 0 ); + } + + private Icon getBlockTextureFromSideInside(AEBaseBlock blk, TileSpatialPylon sp, int displayBits, ForgeDirection ori, ForgeDirection dir) + { + boolean good = (displayBits & sp.DISPLAY_ENABLED) == sp.DISPLAY_ENABLED; + + if ( ori.equals( dir ) || ori.getOpposite().equals( dir ) ) + return good ? ExtraTextures.BlockSpatialPylon_dim.getIcon() : ExtraTextures.BlockSpatialPylon_red.getIcon(); + + if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_MIDDLE ) + return good ? ExtraTextures.BlockSpatialPylonC_dim.getIcon() : ExtraTextures.BlockSpatialPylonC_red.getIcon(); + + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMIN ) + return good ? ExtraTextures.BlockSpatialPylonE_dim.getIcon() : ExtraTextures.BlockSpatialPylonE_red.getIcon(); + + else if ( (displayBits & sp.DISPLAY_MIDDLE) == sp.DISPLAY_ENDMAX ) + return good ? ExtraTextures.BlockSpatialPylonE_dim.getIcon() : ExtraTextures.BlockSpatialPylonE_red.getIcon(); + + return blk.getIcon( 0, 0 ); + } +} diff --git a/client/render/blocks/RenderStorageMonitor.java b/client/render/blocks/RenderStorageMonitor.java new file mode 100644 index 00000000..907453cb --- /dev/null +++ b/client/render/blocks/RenderStorageMonitor.java @@ -0,0 +1,101 @@ +package appeng.client.render.blocks; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import appeng.api.implementations.IPartStorageMonitor; +import appeng.api.storage.data.IAEItemStack; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.tile.AEBaseTile; + +public class RenderStorageMonitor extends BaseBlockRender +{ + + public RenderStorageMonitor() { + super( true, 30 ); + } + + @Override + public void renderTile(AEBaseBlock blk, AEBaseTile tile, Tessellator tess, double x, double y, double z, float f, + RenderBlocks rinstance) + { + IPartStorageMonitor monitor = (IPartStorageMonitor) tile; + IAEItemStack is = ((IAEItemStack) monitor.getDisplayed()); + + if ( is != null && monitor.isPowered() ) + { + FontRenderer fr = Minecraft.getMinecraft().fontRenderer; + + // applyTESRRotation( x, y, z, monitor.getForward(), monitor.getUp() + // ); + + GL11.glPushMatrix(); + try + { + ItemStack sis = is.getItemStack(); + sis.stackSize = 1; + + GL11.glTranslatef( 0.0f, -0.05f, -0.25f ); + GL11.glScalef( 1.0f / 1.5f, 1.0f / 1.5f, 1.0f / 1.5f ); + GL11.glScalef( 1.0f, -1.0f, 0.005f ); + + int k = sis.itemID; + Block block = (k < Block.blocksList.length ? Block.blocksList[k] : null); + if ( sis.getItemSpriteNumber() == 0 && block != null + && RenderBlocks.renderItemIn3d( Block.blocksList[k].getRenderType() ) ) + { + GL11.glRotatef( 25.0f, 1.0f, 0.0f, 0.0f ); + GL11.glRotatef( 15.0f, 0.0f, 1.0f, 0.0f ); + GL11.glRotatef( 30.0f, 0.0f, 1.0f, 0.0f ); + } + int br = 16 << 20 | 16 << 4; + int var11 = br % 65536; + int var12 = br / 65536; + OpenGlHelper.setLightmapTextureCoords( OpenGlHelper.lightmapTexUnit, var11 * 0.8F, var12 * 0.8F ); + + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glDisable( GL12.GL_RESCALE_NORMAL ); + tess.setColorOpaque_F( 1.0f, 1.0f, 1.0f ); + + doRenderItem( sis, tile ); + } + catch (Exception err) + { + err.printStackTrace(); + } + + GL11.glPopMatrix(); + + GL11.glTranslatef( 0.0f, 0.14f, -0.24f ); + GL11.glScalef( 1.0f / 62.0f, 1.0f / 62.0f, 1.0f / 62.0f ); + + long qty = is.getStackSize(); + if ( qty > 999999999999L ) + qty = 999999999999L; + + String msg = Long.toString( qty ); + if ( qty > 1000000000 ) + msg = Long.toString( qty / 1000000000 ) + "B"; + else if ( qty > 1000000 ) + msg = Long.toString( qty / 1000000 ) + "M"; + else if ( qty > 9999 ) + msg = Long.toString( qty / 1000 ) + "K"; + + int width = fr.getStringWidth( msg ); + GL11.glTranslatef( -0.5f * width, 0.0f, -1.0f ); + fr.drawString( msg, 0, 0, 0 ); + } + } + +} diff --git a/client/render/blocks/RenderTinyTNT.java b/client/render/blocks/RenderTinyTNT.java new file mode 100644 index 00000000..bb8f1f8e --- /dev/null +++ b/client/render/blocks/RenderTinyTNT.java @@ -0,0 +1,33 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; + +public class RenderTinyTNT extends BaseBlockRender +{ + + public RenderTinyTNT() { + super( false, 0 ); + } + + @Override + public void renderInventory(AEBaseBlock block, ItemStack is, RenderBlocks renderer) + { + renderer.setRenderBounds( 0.25f, 0.0f, 0.25f, 0.75f, 0.5f, 0.75f ); + super.renderInventory( block, is, renderer ); + } + + @Override + public boolean renderInWorld(AEBaseBlock imb, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + renderer.renderAllFaces = true; + renderer.setRenderBounds( 0.25f, 0.0f, 0.25f, 0.75f, 0.5f, 0.75f ); + boolean out = super.renderInWorld( imb, world, x, y, z, renderer ); + renderer.renderAllFaces = false; + return out; + } + +} diff --git a/client/render/blocks/RendererCableBus.java b/client/render/blocks/RendererCableBus.java new file mode 100644 index 00000000..4760b7b8 --- /dev/null +++ b/client/render/blocks/RendererCableBus.java @@ -0,0 +1,51 @@ +package appeng.client.render.blocks; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.world.IBlockAccess; +import appeng.block.AEBaseBlock; +import appeng.client.render.BaseBlockRender; +import appeng.client.render.BusRenderer; +import appeng.tile.AEBaseTile; +import appeng.tile.networking.TileCableBus; + +public class RendererCableBus extends BaseBlockRender +{ + + public RendererCableBus() { + super( true, 30 ); + } + + @Override + public void renderInventory(AEBaseBlock blk, ItemStack is, RenderBlocks renderer) + { + // nothin. + } + + @Override + public boolean renderInWorld(AEBaseBlock block, IBlockAccess world, int x, int y, int z, RenderBlocks renderer) + { + AEBaseTile t = block.getTileEntity( world, x, y, z ); + + if ( t instanceof TileCableBus ) + { + BusRenderer.instance.renderer.renderAllFaces = true; + BusRenderer.instance.renderer.blockAccess = renderer.blockAccess; + ((TileCableBus) t).cb.renderStatic( x, y, z ); + BusRenderer.instance.renderer.renderAllFaces = false; + } + + return true; + } + + @Override + public void renderTile(AEBaseBlock block, AEBaseTile t, Tessellator tess, double x, double y, double z, float f, RenderBlocks renderer) + { + if ( t instanceof TileCableBus ) + { + ((TileCableBus) t).cb.renderDynamic( x, y, z ); + } + } + +} diff --git a/client/render/effects/ChargedOreEffect.java b/client/render/effects/ChargedOreEffect.java new file mode 100644 index 00000000..d36999ad --- /dev/null +++ b/client/render/effects/ChargedOreEffect.java @@ -0,0 +1,25 @@ +package appeng.client.render.effects; + +import net.minecraft.client.particle.EntityReddustFX; +import net.minecraft.world.World; + +public class ChargedOreEffect extends EntityReddustFX +{ + + public ChargedOreEffect(World w, double x, double y, double z, float r, float g, float b) { + super( w, x, y, z, 0.21f, 0.61f, 1.0f ); + + } + + @Override + public int getBrightnessForRender(float par1) + { + int j1 = super.getBrightnessForRender( par1 ); + j1 = Math.max( j1 >> 20, j1 >> 4 ); + j1 += 3; + if ( j1 > 15 ) + j1 = 15; + return j1 << 20 | j1 << 4; + } + +} diff --git a/client/render/effects/LightningEffect.java b/client/render/effects/LightningEffect.java new file mode 100644 index 00000000..182db44a --- /dev/null +++ b/client/render/effects/LightningEffect.java @@ -0,0 +1,199 @@ +package appeng.client.render.effects; + +import java.util.Random; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +import org.lwjgl.opengl.GL11; + +public class LightningEffect extends EntityFX +{ + + final int steps = 5; + static Random rng = new Random(); + double[][] Steps; + + public LightningEffect(World w, double x, double y, double z, double r, double g, double b) { + super( w, x, y, z, r, g, b ); + Steps = new double[steps][3]; + motionX = 0; + motionY = 0; + motionZ = 0; + particleMaxAge = 6; + + // particleMaxAge = 269; + double lastDirectionX = (rng.nextDouble() - 0.5) * 0.9; + double lastDirectionY = (rng.nextDouble() - 0.5) * 0.9; + double lastDirectionZ = (rng.nextDouble() - 0.5) * 0.9; + for (int s = 0; s < steps; s++) + { + Steps[s][0] = lastDirectionX = (lastDirectionX + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + Steps[s][1] = lastDirectionY = (lastDirectionY + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + Steps[s][2] = lastDirectionZ = (lastDirectionZ + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + } + } + + float currentPoint = 0; + + @Override + public int getBrightnessForRender(float par1) + { + int j1 = 13; + return j1 << 20 | j1 << 4; + } + + @Override + public void renderParticle(Tessellator tess, float l, float rX, float rY, float rZ, float rYZ, float rXY) + { + float j = 1.0f; + tess.setColorRGBA_F( this.particleRed * j * 0.9f, this.particleGreen * j * 0.95f, this.particleBlue * j, this.particleAlpha ); + if ( particleAge == 3 ) + { + double lastDirectionX = (rng.nextDouble() - 0.5) * 0.9; + double lastDirectionY = (rng.nextDouble() - 0.5) * 0.9; + double lastDirectionZ = (rng.nextDouble() - 0.5) * 0.9; + for (int s = 0; s < steps; s++) + { + Steps[s][0] = lastDirectionX = (lastDirectionX + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + Steps[s][1] = lastDirectionY = (lastDirectionY + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + Steps[s][2] = lastDirectionZ = (lastDirectionZ + (rng.nextDouble() - 0.5) * 0.9) / 2.0; + } + } + double f6 = this.particleTextureIndexX / 16.0; + double f7 = f6 + 0.0324375F; + double f8 = this.particleTextureIndexY / 16.0; + double f9 = f8 + 0.0324375F; + + f6 = f7; + f8 = f9; + + double scale = 0.02;// 0.02F * this.particleScale; + + double a[] = new double[3]; + double b[] = new double[3]; + + double ox = 0; + double oy = 0; + double oz = 0; + + EntityClientPlayerMP p = Minecraft.getMinecraft().thePlayer; + double offX = -rZ; + double offY = MathHelper.cos( (float) (Math.PI / 2.0f + p.rotationPitch * 0.017453292F) ); + double offZ = rX; + + for (int layer = 0; layer < 2; layer++) + { + if ( layer == 0 ) + { + scale = 0.04; + offX *= 0.001; + offY *= 0.001; + offZ *= 0.001; + tess.setColorRGBA_F( this.particleRed * j * 0.4f, this.particleGreen * j * 0.25f, this.particleBlue * j * 0.45f, this.particleAlpha ); + } + else + { + offX = 0; + offY = 0; + offZ = 0; + scale = 0.02; + tess.setColorRGBA_F( this.particleRed * j * 0.9f, this.particleGreen * j * 0.65f, this.particleBlue * j * 0.85f, this.particleAlpha ); + } + + for (int cycle = 0; cycle < 3; cycle++) + { + clear(); + + double x = (this.prevPosX + (this.posX - this.prevPosX) * (double) l - interpPosX) - offX; + double y = (this.prevPosY + (this.posY - this.prevPosY) * (double) l - interpPosY) - offY; + double z = (this.prevPosZ + (this.posZ - this.prevPosZ) * (double) l - interpPosZ) - offZ; + + for (int s = 0; s < steps; s++) + { + double xN = x + Steps[s][0]; + double yN = y + Steps[s][1]; + double zN = z + Steps[s][2]; + + double xD = xN - x; + double yD = yN - y; + double zD = zN - z; + + if ( cycle == 0 ) + { + ox = (yD * 0) - (1 * zD); + oy = (zD * 0) - (0 * xD); + oz = (xD * 1) - (0 * yD); + } + if ( cycle == 1 ) + { + ox = (yD * 1) - (0 * zD); + oy = (zD * 0) - (1 * xD); + oz = (xD * 0) - (0 * yD); + } + if ( cycle == 2 ) + { + ox = (yD * 0) - (0 * zD); + oy = (zD * 1) - (0 * xD); + oz = (xD * 0) - (1 * yD); + } + + double ss = Math.sqrt( ox * ox + oy * oy + oz * oz ) / ((((double) steps - (double) s) / (double) steps) * scale); + ox /= ss; + oy /= ss; + oz /= ss; + + a[0] = x + ox; + a[1] = y + oy; + a[2] = z + oz; + + b[0] = x; + b[1] = y; + b[2] = z; + + draw( tess, a, b, f6, f8 ); + + x = xN; + y = yN; + z = zN; + } + } + } + + GL11.glPushAttrib( GL11.GL_ALL_ATTRIB_BITS ); + GL11.glDisable( GL11.GL_CULL_FACE ); + tess.draw(); + GL11.glPopAttrib(); + tess.startDrawingQuads(); + } + + boolean hasData = false; + double[] I = new double[3]; + double[] K = new double[3]; + + private void draw(Tessellator tess, double[] a, double[] b, double f6, double f8) + { + if ( hasData ) + { + tess.addVertexWithUV( a[0], a[1], a[2], f6, f8 ); + tess.addVertexWithUV( I[0], I[1], I[2], f6, f8 ); + tess.addVertexWithUV( K[0], K[1], K[2], f6, f8 ); + tess.addVertexWithUV( b[0], b[1], b[2], f6, f8 ); + } + hasData = true; + for (int x = 0; x < 3; x++) + { + I[x] = a[x]; + K[x] = b[x]; + } + } + + private void clear() + { + hasData = false; + } +} diff --git a/client/render/effects/MatterCannonEffect.java b/client/render/effects/MatterCannonEffect.java new file mode 100644 index 00000000..95872c76 --- /dev/null +++ b/client/render/effects/MatterCannonEffect.java @@ -0,0 +1,72 @@ +package appeng.client.render.effects; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityBreakingFX; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.item.Item; +import net.minecraft.util.Icon; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.client.texture.ExtraTextures; + +public class MatterCannonEffect extends EntityBreakingFX +{ + + private Icon particleTextureIndex; + + public MatterCannonEffect(World par1World, double par2, double par4, double par6, Item par8Item) { + super( par1World, par2, par4, par6, par8Item ); + particleGravity = 0; + this.particleBlue = 255; + this.particleGreen = 255; + this.particleRed = 255; + this.particleAlpha = 1.4f; + this.particleScale = 1.1f; + this.motionX = 0.0f; + this.motionY = 0.0f; + this.motionZ = 0.0f; + this.particleTextureIndex = ExtraTextures.BlockMatterCannonParticle.getIcon(); + } + + public void fromItem(ForgeDirection d) + { + this.particleScale *= 1.2f; + } + + @Override + public void onUpdate() + { + super.onUpdate(); + this.particleScale *= 1.19f; + this.particleAlpha *= 0.59f; + } + + @Override + public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7) + { + Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.locationBlocksTexture ); + + float f6 = this.particleTextureIndex.getMinU(); + float f7 = this.particleTextureIndex.getMaxU(); + float f8 = this.particleTextureIndex.getMinV(); + float f9 = this.particleTextureIndex.getMaxV(); + float f10 = 0.05F * this.particleScale; + + float f11 = (float) (this.prevPosX + (this.posX - this.prevPosX) * (double) par2 - interpPosX); + float f12 = (float) (this.prevPosY + (this.posY - this.prevPosY) * (double) par2 - interpPosY); + float f13 = (float) (this.prevPosZ + (this.posZ - this.prevPosZ) * (double) par2 - interpPosZ); + float f14 = 1.0F; + + par1Tessellator.setColorRGBA_F( this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha ); + par1Tessellator.addVertexWithUV( (double) (f11 - par3 * f10 - par6 * f10), (double) (f12 - par4 * f10), (double) (f13 - par5 * f10 - par7 * f10), + (double) f7, (double) f9 ); + par1Tessellator.addVertexWithUV( (double) (f11 - par3 * f10 + par6 * f10), (double) (f12 + par4 * f10), (double) (f13 - par5 * f10 + par7 * f10), + (double) f7, (double) f8 ); + par1Tessellator.addVertexWithUV( (double) (f11 + par3 * f10 + par6 * f10), (double) (f12 + par4 * f10), (double) (f13 + par5 * f10 + par7 * f10), + (double) f6, (double) f8 ); + par1Tessellator.addVertexWithUV( (double) (f11 + par3 * f10 - par6 * f10), (double) (f12 - par4 * f10), (double) (f13 + par5 * f10 - par7 * f10), + (double) f6, (double) f9 ); + } + +} diff --git a/client/render/effects/VibrantEffect.java b/client/render/effects/VibrantEffect.java new file mode 100644 index 00000000..19f749e1 --- /dev/null +++ b/client/render/effects/VibrantEffect.java @@ -0,0 +1,54 @@ +package appeng.client.render.effects; + +import net.minecraft.client.particle.EntityFX; +import net.minecraft.world.World; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class VibrantEffect extends EntityFX +{ + + public VibrantEffect(World par1World, double x, double y, double z, double par8, double par10, double par12) { + super( par1World, x, y, z, par8, par10, par12 ); + float f = this.rand.nextFloat() * 0.1F + 0.8F; + this.particleRed = f * 0.7f; + this.particleGreen = f * 0.89f; + this.particleBlue = f * 0.9f; + this.setParticleTextureIndex( 0 ); + this.setSize( 0.04F, 0.04F ); + this.particleScale *= this.rand.nextFloat() * 0.6F + 1.9F; + this.motionX = 0.0D; + this.motionY = 0.0D; + this.motionZ = 0.0D; + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + this.particleMaxAge = (int) (20.0D / (Math.random() * 0.8D + 0.1D)); + this.noClip = true; + } + + @Override + public float getBrightness(float par1) + { + return 1.0f; + } + + /** + * Called to update the entity's position/logic. + */ + @Override + public void onUpdate() + { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + // this.moveEntity(this.motionX, this.motionY, this.motionZ); + this.particleScale *= 0.95; + + if ( this.particleMaxAge-- <= 0 || this.particleScale < 0.1 ) + { + this.setDead(); + } + } +} diff --git a/client/render/entity/EntityIds.java b/client/render/entity/EntityIds.java new file mode 100644 index 00000000..a67e9b5c --- /dev/null +++ b/client/render/entity/EntityIds.java @@ -0,0 +1,26 @@ +package appeng.client.render.entity; + +import net.minecraft.entity.Entity; +import appeng.entity.EntityChargedQuartz; +import appeng.entity.EntitySingularity; +import appeng.entity.EntityTinyTNTPrimed; + +public class EntityIds +{ + + public static final int TINY_TNT = 10; + public static final int SINGULARITY = 11; + public static final int CHARGED_QUARTZ = 12; + + public static int get(Class droppedEntity) + { + if ( droppedEntity == EntityTinyTNTPrimed.class ) + return TINY_TNT; + if ( droppedEntity == EntitySingularity.class ) + return SINGULARITY; + if ( droppedEntity == EntityChargedQuartz.class ) + return CHARGED_QUARTZ; + + throw new RuntimeException( "Missing entity id: " + droppedEntity.getName() ); + } +} diff --git a/client/render/entity/RenderTinyTNTPrimed.java b/client/render/entity/RenderTinyTNTPrimed.java new file mode 100644 index 00000000..a369f08b --- /dev/null +++ b/client/render/entity/RenderTinyTNTPrimed.java @@ -0,0 +1,85 @@ +package appeng.client.render.entity; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; + +import org.lwjgl.opengl.GL11; + +import appeng.entity.EntityTinyTNTPrimed; + +public class RenderTinyTNTPrimed extends Render +{ + + private RenderBlocks blockRenderer = new RenderBlocks(); + + public RenderTinyTNTPrimed() { + this.shadowSize = 0.5F; + this.renderManager = RenderManager.instance; + } + + public void renderPrimedTNT(EntityTinyTNTPrimed tnt, double x, double y, double z, float var1, float life) + { + GL11.glPushMatrix(); + GL11.glTranslatef( (float) x, (float) y - 0.25f, (float) z ); + float f2; + + if ( (float) tnt.fuse - life + 1.0F < 10.0F ) + { + f2 = 1.0F - ((float) tnt.fuse - life + 1.0F) / 10.0F; + + if ( f2 < 0.0F ) + { + f2 = 0.0F; + } + + if ( f2 > 1.0F ) + { + f2 = 1.0F; + } + + f2 *= f2; + f2 *= f2; + float f3 = 1.0F + f2 * 0.3F; + GL11.glScalef( f3, f3, f3 ); + } + + GL11.glScalef( 0.5f, 0.5f, 0.5f ); + f2 = (1.0F - ((float) tnt.fuse - life + 1.0F) / 100.0F) * 0.8F; + this.bindEntityTexture( tnt ); + this.blockRenderer.renderBlockAsItem( Block.tnt, 0, tnt.getBrightness( life ) ); + + if ( tnt.fuse / 5 % 2 == 0 ) + { + GL11.glDisable( GL11.GL_TEXTURE_2D ); + GL11.glDisable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_BLEND ); + GL11.glBlendFunc( GL11.GL_SRC_ALPHA, GL11.GL_DST_ALPHA ); + GL11.glColor4f( 1.0F, 1.0F, 1.0F, f2 ); + this.blockRenderer.renderBlockAsItem( Block.tnt, 0, 1.0F ); + GL11.glColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); + GL11.glDisable( GL11.GL_BLEND ); + GL11.glEnable( GL11.GL_LIGHTING ); + GL11.glEnable( GL11.GL_TEXTURE_2D ); + } + + GL11.glPopMatrix(); + } + + @Override + public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9) + { + this.renderPrimedTNT( (EntityTinyTNTPrimed) par1Entity, par2, par4, par6, par8, par9 ); + } + + @Override + protected ResourceLocation getEntityTexture(Entity entity) + { + return TextureMap.locationBlocksTexture; + } + +} diff --git a/client/texture/CableBusTextures.java b/client/texture/CableBusTextures.java new file mode 100644 index 00000000..2d247eba --- /dev/null +++ b/client/texture/CableBusTextures.java @@ -0,0 +1,101 @@ +package appeng.client.texture; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.Icon; +import net.minecraft.util.ResourceLocation; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public enum CableBusTextures +{ + + Channels00("MECableSmart00"), Channels01("MECableSmart01"), Channels02("MECableSmart02"), Channels03("MECableSmart03"), Channels10("MECableSmart10"), Channels11( + "MECableSmart11"), Channels12("MECableSmart12"), Channels13("MECableSmart13"), Channels14("MECableSmart14"), Channels04("MECableSmart04"), + + LevelEmitterTorchOn("ItemPart.LevelEmitterOn"), BlockWirelessOn("BlockWirelessOn"), + + BlockTransPlane("BlockTransPlaneOn"), + + BlockP2PTunnel2("ItemPart.P2PTunnel2"), BlockP2PTunnel3("ItemPart.P2PTunnel3"), + + MEWaiting("MEWaiting"), + + PartMonitorSides("PartMonitorSides"), PartMonitorBack("PartMonitorBack"), + + Transparent("Transparent"), PartMonitorSidesStatus("PartMonitorSidesStatus"), PartMonitorSidesStatusLights("PartMonitorSidesStatusLights"), + + PartMonitor_Solid("PartMonitor_Solid"), PartMonitor_Colored("PartMonitor_Colored"), PartMonitor_Bright("PartMonitor_Bright"), + + PartPatternTerm_Bright("PartPatternTerm_Bright"), PartPatternTerm_Colored("PartPatternTerm_Colored"), PartPatternTerm_Dark("PartPatternTerm_Dark"), PartPatternTerm_Solid( + "PartPatternTerm_Solid"), + + PartConvMonitor_Bright("PartConvMonitor_Bright"), PartConvMonitor_Colored("PartConvMonitor_Colored"), PartConvMonitor_Dark("PartConvMonitor_Dark"), PartConvMonitor_Solid( + "PartConvMonitor_Solid"), + + PartCraftingMonitor_Bright("PartCraftingMonitor_Bright"), PartCraftingMonitor_Colored("PartCraftingMonitor_Colored"), PartCraftingMonitor_Dark( + "PartCraftingMonitor_Dark"), PartCraftingMonitor_Solid("PartCraftingMonitor_Solid"), + + PartCraftingTerm_Bright("PartCraftingTerm_Bright"), PartCraftingTerm_Colored("PartCraftingTerm_Colored"), PartCraftingTerm_Dark("PartCraftingTerm_Dark"), PartCraftingTerm_Solid( + "PartCraftingTerm_Solid"), + + PartStorageMonitor_Bright("PartStorageMonitor_Bright"), PartStorageMonitor_Colored("PartStorageMonitor_Colored"), PartStorageMonitor_Dark( + "PartStorageMonitor_Dark"), PartStorageMonitor_Solid("PartStorageMonitor_Solid"), + + PartTerminal_Bright("PartTerminal_Bright"), PartTerminal_Colored("PartTerminal_Colored"), PartTerminal_Dark("PartTerminal_Dark"), PartTerminal_Solid( + "PartTerminal_Solid"), + + MECable_Green("MECable_Green"), MECable_Grey("MECable_Grey"), MECable_LightBlue("MECable_LightBlue"), MECable_LightGrey("MECable_LightGrey"), MECable_Lime( + "MECable_Lime"), MECable_Magenta("MECable_Magenta"), MECable_Orange("MECable_Orange"), MECable_Pink("MECable_Pink"), MECable_Purple( + "MECable_Purple"), MECable_Red("MECable_Red"), MECable_White("MECable_White"), MECable_Yellow("MECable_Yellow"), MECable_Black("MECable_Black"), MECable_Blue( + "MECable_Blue"), MECable_Brown("MECable_Brown"), MECable_Cyan("MECable_Cyan"), + + MESmart_Black("MESmart_Black"), MESmart_Blue("MESmart_Blue"), MESmart_Brown("MESmart_Brown"), MESmart_Cyan("MESmart_Cyan"), MESmart_Gray("MESmart_Gray"), MESmart_Green( + "MESmart_Green"), MESmart_LightBlue("MESmart_LightBlue"), MESmart_LightGrey("MESmart_LightGrey"), MESmart_Lime("MESmart_Lime"), MESmart_Magenta( + "MESmart_Magenta"), MESmart_Orange("MESmart_Orange"), MESmart_Pink("MESmart_Pink"), MESmart_Purple("MESmart_Purple"), MESmart_Red("MESmart_Red"), MESmart_White( + "MESmart_White"), MESmart_Yellow("MESmart_Yellow"), + + MECovered_Black("MECovered_Black"), MECovered_Blue("MECovered_Blue"), MECovered_Brown("MECovered_Brown"), MECovered_Cyan("MECovered_Cyan"), MECovered_Gray( + "MECovered_Gray"), MECovered_Green("MECovered_Green"), MECovered_LightBlue("MECovered_LightBlue"), MECovered_LightGrey("MECovered_LightGrey"), MECovered_Lime( + "MECovered_Lime"), MECovered_Magenta("MECovered_Magenta"), MECovered_Orange("MECovered_Orange"), MECovered_Pink("MECovered_Pink"), MECovered_Purple( + "MECovered_Purple"), MECovered_Red("MECovered_Red"), MECovered_White("MECovered_White"), MECovered_Yellow("MECovered_Yellow"), + + BlockAnnihilationPlaneOn("BlockAnnihilationPlaneOn"), + + BlockFormPlaneOn("BlockFormPlaneOn"), + + ItemPartLevelEmitterOn("ItemPart.LevelEmitterOn.png"), PartTransitionPlaneBack("PartTransitionPlaneBack"); + + final private String name; + public Icon icon; + + public static ResourceLocation GuiTexture(String string) + { + return null; + } + + public String getName() + { + return name; + } + + private CableBusTextures(String name) { + this.name = name; + } + + public Icon getIcon() + { + return icon; + } + + public void registerIcon(TextureMap map) + { + icon = map.registerIcon( "appliedenergistics2:" + name ); + } + + @SideOnly(Side.CLIENT) + public static Icon getMissing() + { + return ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture( TextureMap.locationBlocksTexture )).getAtlasSprite( "missingno" ); + } +} diff --git a/client/texture/ExtraTextures.java b/client/texture/ExtraTextures.java new file mode 100644 index 00000000..99531e2f --- /dev/null +++ b/client/texture/ExtraTextures.java @@ -0,0 +1,81 @@ +package appeng.client.texture; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.Icon; +import net.minecraft.util.ResourceLocation; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public enum ExtraTextures +{ + BlockVibrationChamberFrontOn("BlockVibrationChamberFrontOn"), + + OreQuartzStone("OreQuartzStone"), + + MEChest("BlockMEChest"), BlockMEChestItems("BlockMEChestItems"), + + BlockControllerPowered("BlockControllerPowered"), BlockControllerColumnPowered("BlockControllerColumnPowered"), BlockControllerColumn( + "BlockControllerColumn"), BlockControllerLights("BlockControllerLights"), BlockControllerColumnLights("BlockControllerColumnLights"), BlockControllerColumnConflict( + "BlockControllerColumnConflict"), BlockControllerConflict("BlockControllerConflict"), BlockControllerInsideA("BlockControllerInsideA"), BlockControllerInsideB( + "BlockControllerInsideB"), + + BlockChargerInside("BlockChargerInside"), + + BlockContainmentWallMerged("BlockContainmentWallMerged"), BlockHeatVentMerged("BlockHeatVentMerged"), + + MEStorageCellTextures("MEStorageCellTextures"), White("White"), + + BlockInterfaceAlternate("BlockInterfaceAlternate"), BlockInterfaceAlternateArrow("BlockInterfaceAlternateArrow"), + + BlockMatterCannonParticle("BlockMatterCannonParticle"), BlockEnergyParticle("BlockEnergyParticle"), + + GlassFrame("BlockQuartzGlassFrame"), + + MEDenseEnergyCell0("BlockDenseEnergyCell0"), MEDenseEnergyCell1("BlockDenseEnergyCell1"), MEDenseEnergyCell2("BlockDenseEnergyCell2"), MEDenseEnergyCell3( + "BlockDenseEnergyCell3"), MEDenseEnergyCell4("BlockDenseEnergyCell4"), MEDenseEnergyCell5("BlockDenseEnergyCell5"), MEDenseEnergyCell6( + "BlockDenseEnergyCell6"), MEDenseEnergyCell7("BlockDenseEnergyCell7"), + + MEEnergyCell0("BlockEnergyCell0"), MEEnergyCell1("BlockEnergyCell1"), MEEnergyCell2("BlockEnergyCell2"), MEEnergyCell3("BlockEnergyCell3"), MEEnergyCell4( + "BlockEnergyCell4"), MEEnergyCell5("BlockEnergyCell5"), MEEnergyCell6("BlockEnergyCell6"), MEEnergyCell7("BlockEnergyCell7"), + + BlockSpatialPylon_dim("BlockSpatialPylon_dim"), BlockSpatialPylon_red("BlockSpatialPylon_red"), + + BlockSpatialPylonC("BlockSpatialPylon_spanned"), BlockSpatialPylonC_dim("BlockSpatialPylon_spanned_dim"), BlockSpatialPylonC_red( + "BlockSpatialPylon_spanned_red"), + + BlockSpatialPylonE("BlockSpatialPylon_end"), BlockSpatialPylonE_dim("BlockSpatialPylon_end_dim"), BlockSpatialPylonE_red("BlockSpatialPylon_end_red"); + + final private String name; + public Icon icon; + + public static ResourceLocation GuiTexture(String string) + { + return new ResourceLocation( "appliedenergistics2", "textures/" + string ); + } + + public String getName() + { + return name; + } + + private ExtraTextures(String name) { + this.name = name; + } + + public Icon getIcon() + { + return icon; + } + + public void registerIcon(TextureMap map) + { + icon = map.registerIcon( "appliedenergistics2:" + name ); + } + + @SideOnly(Side.CLIENT) + public static Icon getMissing() + { + return ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture( TextureMap.locationBlocksTexture )).getAtlasSprite( "missingno" ); + } +} diff --git a/client/texture/FlipableIcon.java b/client/texture/FlipableIcon.java new file mode 100644 index 00000000..16ea5f18 --- /dev/null +++ b/client/texture/FlipableIcon.java @@ -0,0 +1,102 @@ +package appeng.client.texture; + +import net.minecraft.util.Icon; + +public class FlipableIcon implements Icon +{ + + protected Icon original; + boolean flip_u; + boolean flip_v; + + public FlipableIcon(Icon o) { + original = o; + flip_u = false; + flip_v = false; + } + + @Override + public int getIconWidth() + { + return original.getIconWidth(); + } + + @Override + public int getIconHeight() + { + return original.getIconHeight(); + } + + @Override + public float getMinU() + { + if ( flip_u ) + return original.getMaxU(); + return original.getMinU(); + } + + @Override + public float getMaxU() + { + if ( flip_u ) + return original.getMinU(); + return original.getMaxU(); + } + + @Override + public float getInterpolatedU(double px) + { + if ( flip_u ) + return original.getInterpolatedU( 16 - px ); + return original.getInterpolatedU( px ); + } + + @Override + public float getMinV() + { + if ( flip_v ) + return original.getMaxV(); + return original.getMinV(); + } + + @Override + public float getMaxV() + { + if ( flip_v ) + return original.getMinV(); + return original.getMaxV(); + } + + @Override + public float getInterpolatedV(double px) + { + if ( flip_v ) + return original.getInterpolatedV( 16 - px ); + return original.getInterpolatedV( px ); + } + + @Override + public String getIconName() + { + return original.getIconName(); + } + + public Icon getOriginal() + { + return original; + } + + public void setFlip(boolean u, boolean v) + { + flip_u = u; + flip_v = v; + } + + public int setFlip(int orientation) + { + flip_u = (orientation & 8) == 8; + flip_v = (orientation & 16) == 16; + return orientation & 7; + } + +} diff --git a/client/texture/FullIcon.java b/client/texture/FullIcon.java new file mode 100644 index 00000000..11f5009e --- /dev/null +++ b/client/texture/FullIcon.java @@ -0,0 +1,81 @@ +package appeng.client.texture; + +import net.minecraft.util.Icon; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class FullIcon implements Icon +{ + + private Icon p; + + public FullIcon(Icon o) { + p = o; + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinU() + { + return p.getMinU(); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxU() + { + return p.getMaxU(); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedU(double d0) + { + if ( d0 > 8.0 ) + return p.getMaxU(); + return p.getMinU(); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinV() + { + return p.getMinV(); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxV() + { + return p.getMaxV(); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedV(double d0) + { + if ( d0 > 8.0 ) + return p.getMaxV(); + return p.getMinV(); + } + + @Override + @SideOnly(Side.CLIENT) + public String getIconName() + { + return p.getIconName(); + } + + @Override + public int getIconWidth() + { + return p.getIconWidth(); + } + + @Override + public int getIconHeight() + { + return p.getIconHeight(); + } + +} diff --git a/client/texture/OffsetIcon.java b/client/texture/OffsetIcon.java new file mode 100644 index 00000000..99c96f2e --- /dev/null +++ b/client/texture/OffsetIcon.java @@ -0,0 +1,92 @@ +package appeng.client.texture; + +import net.minecraft.util.Icon; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class OffsetIcon implements Icon +{ + + final float offsetX; + final float offsetY; + + private Icon p; + + public OffsetIcon(Icon o, float x, float y) { + p = o; + offsetX = x; + offsetY = y; + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinU() + { + return u( 0 - offsetX ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxU() + { + return u( 16 - offsetX ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedU(double d0) + { + return u( d0 - offsetX ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinV() + { + return v( 0 - offsetY ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxV() + { + return v( 16 - offsetY ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedV(double d0) + { + return v( d0 - offsetY ); + } + + private float v(double d) + { + return p.getInterpolatedV( Math.min( 16.0, Math.max( 0.0, d ) ) ); + } + + private float u(double d) + { + return p.getInterpolatedU( Math.min( 16.0, Math.max( 0.0, d ) ) ); + } + + @Override + @SideOnly(Side.CLIENT) + public String getIconName() + { + return p.getIconName(); + } + + @Override + public int getIconWidth() + { + return p.getIconWidth(); + } + + @Override + public int getIconHeight() + { + return p.getIconHeight(); + } + +} diff --git a/client/texture/TaughtIcon.java b/client/texture/TaughtIcon.java new file mode 100644 index 00000000..9638d75c --- /dev/null +++ b/client/texture/TaughtIcon.java @@ -0,0 +1,98 @@ +package appeng.client.texture; + +import net.minecraft.util.Icon; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class TaughtIcon implements Icon +{ + + final float tightness; + + private Icon p; + + public TaughtIcon(Icon o, float tightness) { + p = o; + this.tightness = tightness; + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinU() + { + return u( 0 ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxU() + { + return u( 16 ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedU(double d0) + { + return u( d0 ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMinV() + { + return v( 0 ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getMaxV() + { + return v( 16 ); + } + + @Override + @SideOnly(Side.CLIENT) + public float getInterpolatedV(double d0) + { + return v( d0 ); + } + + private float v(double d) + { + if ( d < 8 ) + d -= tightness; + if ( d > 8 ) + d += tightness; + return p.getInterpolatedV( Math.min( 16.0, Math.max( 0.0, d ) ) ); + } + + private float u(double d) + { + if ( d < 8 ) + d -= tightness; + if ( d > 8 ) + d += tightness; + return p.getInterpolatedU( Math.min( 16.0, Math.max( 0.0, d ) ) ); + } + + @Override + @SideOnly(Side.CLIENT) + public String getIconName() + { + return p.getIconName(); + } + + @Override + public int getIconWidth() + { + return p.getIconWidth(); + } + + @Override + public int getIconHeight() + { + return p.getIconHeight(); + } + +} diff --git a/client/texture/TmpFlipableIcon.java b/client/texture/TmpFlipableIcon.java new file mode 100644 index 00000000..66d9d8cd --- /dev/null +++ b/client/texture/TmpFlipableIcon.java @@ -0,0 +1,20 @@ +package appeng.client.texture; + +import net.minecraft.util.Icon; + +public class TmpFlipableIcon extends FlipableIcon +{ + + public TmpFlipableIcon() { + super( null ); + } + + public void setOriginal(Icon i) + { + while (i instanceof FlipableIcon) + i = ((FlipableIcon) i).getOriginal(); + + original = i; + } + +} diff --git a/container/AEBaseContainer.java b/container/AEBaseContainer.java new file mode 100644 index 00000000..d8f67aa3 --- /dev/null +++ b/container/AEBaseContainer.java @@ -0,0 +1,434 @@ +package appeng.container; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.networking.energy.IEnergySource; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.data.IAEItemStack; +import appeng.client.me.InternalSlotME; +import appeng.client.me.SlotME; +import appeng.container.slot.ISlotPlayerSide; +import appeng.container.slot.SlotCraftingMatrix; +import appeng.container.slot.SlotDisabled; +import appeng.container.slot.SlotFake; +import appeng.container.slot.SlotInaccessable; +import appeng.container.slot.SlotPlayerHotBar; +import appeng.container.slot.SlotPlayerInv; +import appeng.helpers.InventoryAction; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; + +public abstract class AEBaseContainer extends Container +{ + + final InventoryPlayer invPlayer; + final TileEntity tileEntity; + + protected IMEInventoryHandler cellInv; + protected IEnergySource powerSrc; + + public AEBaseContainer(InventoryPlayer ip, TileEntity te) { + invPlayer = ip; + tileEntity = te; + } + + public TileEntity getTileEntity() + { + return tileEntity; + } + + @Override + public boolean canInteractWith(EntityPlayer entityplayer) + { + if ( tileEntity instanceof IInventory ) + return ((IInventory) tileEntity).isUseableByPlayer( entityplayer ); + return true; + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer p, int idx) + { + if ( Platform.isClient() ) + return null; + + boolean hasMETiles = false; + for (Object is : this.inventorySlots) + { + if ( is instanceof InternalSlotME ) + { + hasMETiles = true; + break; + } + } + + if ( hasMETiles && Platform.isClient() ) + { + return null; + } + + ItemStack tis = null; + Slot clickSlot = (Slot) this.inventorySlots.get( idx ); + + if ( clickSlot instanceof SlotDisabled || clickSlot instanceof SlotInaccessable ) + return null; + if ( clickSlot != null && clickSlot.getHasStack() ) + { + tis = clickSlot.getStack(); + + if ( tis == null ) + return null; + + List selectedSlots = new ArrayList(); + + /** + * Gather a list of valid destinations. + */ + if ( clickSlot instanceof ISlotPlayerSide ) + { + tis = shiftStoreItem( tis ); + + // target slots in the container... + for (int x = 0; x < this.inventorySlots.size(); x++) + { + Slot cs = (Slot) this.inventorySlots.get( x ); + + if ( !(cs instanceof ISlotPlayerSide) && !(cs instanceof SlotFake) && !(cs instanceof SlotCraftingMatrix) ) + { + if ( cs.isItemValid( tis ) ) + selectedSlots.add( cs ); + } + } + } + else + { + // target slots in the container... + for (int x = 0; x < this.inventorySlots.size(); x++) + { + Slot cs = (Slot) this.inventorySlots.get( x ); + + if ( (cs instanceof ISlotPlayerSide) && !(cs instanceof SlotFake) && !(cs instanceof SlotCraftingMatrix) ) + { + if ( cs.isItemValid( tis ) ) + selectedSlots.add( cs ); + } + } + } + + /** + * Handle Fake Slot Shift clicking. + */ + if ( selectedSlots.isEmpty() && clickSlot instanceof ISlotPlayerSide ) + { + if ( tis != null ) + { + // target slots in the container... + for (int x = 0; x < this.inventorySlots.size(); x++) + { + Slot cs = (Slot) this.inventorySlots.get( x ); + ItemStack dest = cs.getStack(); + + if ( !(cs instanceof ISlotPlayerSide) && cs instanceof SlotFake ) + { + if ( Platform.isSameItem( dest, tis ) ) + return null; + else if ( dest == null ) + { + cs.putStack( tis != null ? tis.copy() : null ); + cs.onSlotChanged(); + updateSlot( cs ); + return null; + } + } + } + } + } + + if ( tis != null ) + { + // find partials.. + for (Slot d : selectedSlots) + { + if ( d instanceof SlotDisabled || d instanceof SlotME ) + continue; + + if ( d.isItemValid( tis ) && tis != null ) + { + if ( d.getHasStack() ) + { + ItemStack t = d.getStack(); + + if ( tis != null && Platform.isSameItem( tis, t ) ) // t.isItemEqual(tis)) + { + int maxSize = t.getMaxStackSize(); + if ( maxSize > d.getSlotStackLimit() ) + maxSize = d.getSlotStackLimit(); + + int placeAble = maxSize - t.stackSize; + + if ( tis.stackSize < placeAble ) + { + placeAble = tis.stackSize; + } + + t.stackSize += placeAble; + tis.stackSize -= placeAble; + + if ( tis.stackSize <= 0 ) + { + clickSlot.putStack( null ); + d.onSlotChanged(); + + // if ( hasMETiles ) updateClient(); + + updateSlot( clickSlot ); + updateSlot( d ); + return null; + } + else + updateSlot( d ); + } + } + } + } + + // any match.. + for (Slot d : selectedSlots) + { + if ( d instanceof SlotDisabled || d instanceof SlotME ) + continue; + + if ( d.isItemValid( tis ) && tis != null ) + { + if ( d.getHasStack() ) + { + ItemStack t = d.getStack(); + + if ( tis != null && Platform.isSameItem( t, tis ) ) + { + int maxSize = t.getMaxStackSize(); + if ( d.getSlotStackLimit() < maxSize ) + maxSize = d.getSlotStackLimit(); + + int placeAble = maxSize - t.stackSize; + + if ( tis.stackSize < placeAble ) + { + placeAble = tis.stackSize; + } + + t.stackSize += placeAble; + tis.stackSize -= placeAble; + + if ( tis.stackSize <= 0 ) + { + clickSlot.putStack( null ); + d.onSlotChanged(); + + // if ( worldEntity != null ) + // worldEntity.onInventoryChanged(); + // if ( hasMETiles ) updateClient(); + + updateSlot( clickSlot ); + updateSlot( d ); + return null; + } + else + updateSlot( d ); + } + } + else + { + int maxSize = tis.getMaxStackSize(); + if ( maxSize > d.getSlotStackLimit() ) + maxSize = d.getSlotStackLimit(); + + ItemStack tmp = tis.copy(); + if ( tmp.stackSize > maxSize ) + tmp.stackSize = maxSize; + + tis.stackSize -= tmp.stackSize; + d.putStack( tmp ); + + if ( tis.stackSize <= 0 ) + { + clickSlot.putStack( null ); + d.onSlotChanged(); + + // if ( worldEntity != null ) + // worldEntity.onInventoryChanged(); + // if ( hasMETiles ) updateClient(); + + updateSlot( clickSlot ); + updateSlot( d ); + return null; + } + else + updateSlot( d ); + } + } + } + } + + clickSlot.putStack( tis != null ? tis.copy() : null ); + } + + updateSlot( clickSlot ); + return null; + } + + private void updateSlot(Slot clickSlot) + { + detectAndSendChanges(); + } + + protected void bindPlayerInventory(InventoryPlayer inventoryPlayer, int offset_x, int offset_y) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 9; j++) + { + addSlotToContainer( new SlotPlayerInv( inventoryPlayer, j + i * 9 + 9, 8 + j * 18 + offset_x, offset_y + i * 18 ) ); + } + } + + for (int i = 0; i < 9; i++) + { + addSlotToContainer( new SlotPlayerHotBar( inventoryPlayer, i, 8 + i * 18 + offset_x, 58 + offset_y ) ); + } + } + + public ItemStack shiftStoreItem(ItemStack input) + { + if ( powerSrc == null || cellInv == null ) + return input; + IAEItemStack ais = Platform.poweredInsert( powerSrc, cellInv, AEApi.instance().storage().createItemStack( input ) ); + if ( ais == null ) + return null; + return ais.getItemStack(); + } + + public void doAction(EntityPlayerMP player, InventoryAction action, int slot, IAEItemStack slotItem) + { + /* + * boolean isValidSlot = true; + * + * if ( slot < 0 || slot >= inventorySlots.size() ) isValidSlot = false; + */ + + switch (action) + { + case SHIFT_CLICK: + if ( powerSrc == null || cellInv == null ) + return; + + if ( slotItem != null ) + { + IAEItemStack ais = slotItem.copy(); + ItemStack myItem = ais.getItemStack(); + + ais.setStackSize( myItem.getMaxStackSize() ); + + InventoryAdaptor adp = InventoryAdaptor.getAdaptor( player.inventory, ForgeDirection.UNKNOWN ); + myItem.stackSize = (int) ais.getStackSize(); + myItem = adp.simulateAdd( myItem ); + + if ( myItem != null ) + ais.setStackSize( ais.getStackSize() - myItem.stackSize ); + + ais = Platform.poweredExtraction( powerSrc, cellInv, ais ); + if ( ais != null ) + adp.addItems( ais.getItemStack() ); + } + break; + case PICKUP_OR_SETDOWN: + if ( powerSrc == null || cellInv == null ) + return; + + if ( player.inventory.getItemStack() == null ) + { + if ( slotItem != null ) + { + IAEItemStack ais = slotItem.copy(); + ais.setStackSize( ais.getItemStack().getMaxStackSize() ); + ais = Platform.poweredExtraction( powerSrc, cellInv, ais ); + if ( ais != null ) + player.inventory.setItemStack( ais.getItemStack() ); + else + player.inventory.setItemStack( null ); + player.updateHeldItem(); + } + } + else + { + IAEItemStack ais = AEApi.instance().storage().createItemStack( player.inventory.getItemStack() ); + ais = Platform.poweredInsert( powerSrc, cellInv, ais ); + if ( ais != null ) + player.inventory.setItemStack( ais.getItemStack() ); + else + player.inventory.setItemStack( null ); + player.updateHeldItem(); + } + + break; + case SPLIT_OR_PLACESINGLE: + if ( powerSrc == null || cellInv == null ) + return; + + if ( player.inventory.getItemStack() == null ) + { + if ( slotItem != null ) + { + IAEItemStack ais = slotItem.copy(); + long stackSize = Math.min( ais.getItemStack().getMaxStackSize(), ais.getStackSize() ); + ais.setStackSize( (stackSize + 1) >> 1 ); + ais = Platform.poweredExtraction( powerSrc, cellInv, ais ); + if ( ais != null ) + player.inventory.setItemStack( ais.getItemStack() ); + else + player.inventory.setItemStack( null ); + player.updateHeldItem(); + } + } + else + { + IAEItemStack ais = AEApi.instance().storage().createItemStack( player.inventory.getItemStack() ); + ais.setStackSize( 1 ); + ais = Platform.poweredInsert( powerSrc, cellInv, ais ); + if ( ais == null ) + { + ItemStack is = player.inventory.getItemStack(); + is.stackSize--; + if ( is.stackSize <= 0 ) + player.inventory.setItemStack( null ); + player.updateHeldItem(); + } + } + + break; + case CREATIVE_DUPLICATE: + if ( player.capabilities.isCreativeMode && slotItem != null ) + { + ItemStack is = slotItem.getItemStack(); + is.stackSize = is.getMaxStackSize(); + player.inventory.setItemStack( is ); + player.updateHeldItem(); + } + break; + case MOVE_REGION: + break; + default: + break; + } + } +} diff --git a/container/ContainerNull.java b/container/ContainerNull.java new file mode 100644 index 00000000..79f110d7 --- /dev/null +++ b/container/ContainerNull.java @@ -0,0 +1,18 @@ +package appeng.container; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; + +/* + * Totaly useless container that does nothing. + */ +public class ContainerNull extends Container +{ + + @Override + public boolean canInteractWith(EntityPlayer entityplayer) + { + return false; + } + +} diff --git a/container/implementations/ContainerChest.java b/container/implementations/ContainerChest.java new file mode 100644 index 00000000..366c004c --- /dev/null +++ b/container/implementations/ContainerChest.java @@ -0,0 +1,23 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.tile.storage.TileChest; + +public class ContainerChest extends AEBaseContainer +{ + + TileChest myte; + + public ContainerChest(InventoryPlayer ip, TileChest te) { + super( ip, te ); + myte = te; + + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.STORAGE_CELLS, myte, 1, 80, 37 ) ); + + bindPlayerInventory( ip, 0, 166 - /* height of playerinventory */82 ); + } + +} diff --git a/container/implementations/ContainerCondenser.java b/container/implementations/ContainerCondenser.java new file mode 100644 index 00000000..57733ae3 --- /dev/null +++ b/container/implementations/ContainerCondenser.java @@ -0,0 +1,106 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ICrafting; +import appeng.api.config.CondenserOuput; +import appeng.api.config.Settings; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.tile.misc.TileCondenser; +import appeng.util.Platform; +import buildcraft.core.gui.slots.SlotOutput; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ContainerCondenser extends AEBaseContainer +{ + + TileCondenser myte; + + public ContainerCondenser(InventoryPlayer ip, TileCondenser te) { + super( ip, te ); + myte = te; + + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.TRASH, te, 0, 51, 52 ) ); + addSlotToContainer( new SlotOutput( te, 1, 105, 52 ) ); + addSlotToContainer( (new SlotRestrictedInput( PlaceableItemType.STORAGE_COMPONENT, te.getInternalInventory(), 2, 101, 26 )).setStackLimit( 1 ) ); + + bindPlayerInventory( ip, 0, 197 - /* height of playerinventory */82 ); + } + + public int requiredEnergy = 0; + public int storedPower = 0; + public CondenserOuput output = CondenserOuput.TRASH; + + @Override + public void detectAndSendChanges() + { + if ( Platform.isServer() ) + { + double maxStorage = this.myte.getStorage(); + double requiredEnergy = this.myte.getRequiredPower(); + int maxDisplay = requiredEnergy == 0 ? (int) maxStorage : (int) Math.min( requiredEnergy, maxStorage ); + + for (int i = 0; i < this.crafters.size(); ++i) + { + boolean changed = false; + + ICrafting icrafting = (ICrafting) this.crafters.get( i ); + + if ( this.requiredEnergy != maxDisplay ) + { + icrafting.sendProgressBarUpdate( this, 0, (int) maxDisplay ); + changed = true; + } + + if ( this.storedPower != this.myte.storedPower ) + { + icrafting.sendProgressBarUpdate( this, 1, (int) this.myte.storedPower ); + changed = true; + } + + if ( this.output != this.myte.getConfigManager().getSetting( Settings.CONDENSER_OUTPUT ) ) + { + icrafting.sendProgressBarUpdate( this, 2, (int) this.myte.getConfigManager().getSetting( Settings.CONDENSER_OUTPUT ).ordinal() ); + changed = true; + } + + if ( changed ) + { + // if the bars changed an item was probably made, so just send shit! + ((EntityPlayerMP) icrafting).playerInventoryBeingManipulated = false; + } + } + + this.requiredEnergy = (int) maxDisplay; + this.storedPower = (int) this.myte.storedPower; + this.output = (CondenserOuput) this.myte.getConfigManager().getSetting( Settings.CONDENSER_OUTPUT ); + } + + super.detectAndSendChanges(); + } + + @Override + @SideOnly(Side.CLIENT) + public void updateProgressBar(int idx, int value) + { + if ( idx == 0 ) + { + this.requiredEnergy = value; + } + + if ( idx == 1 ) + { + this.storedPower = value; + } + + if ( idx == 2 ) + { + this.output = CondenserOuput.values()[value]; + } + + } + +} diff --git a/container/implementations/ContainerDrive.java b/container/implementations/ContainerDrive.java new file mode 100644 index 00000000..795391fa --- /dev/null +++ b/container/implementations/ContainerDrive.java @@ -0,0 +1,27 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.tile.storage.TileDrive; + +public class ContainerDrive extends AEBaseContainer +{ + + TileDrive myte; + + public ContainerDrive(InventoryPlayer ip, TileDrive te) { + super( ip, te ); + myte = te; + + for (int y = 0; y < 5; y++) + for (int x = 0; x < 2; x++) + { + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.STORAGE_CELLS, te, x + y * 2, 71 + x * 18, 14 + y * 18 ) ); + } + + bindPlayerInventory( ip, 0, 199 - /* height of playerinventory */82 ); + } + +} diff --git a/container/implementations/ContainerGrinder.java b/container/implementations/ContainerGrinder.java new file mode 100644 index 00000000..8fc32e38 --- /dev/null +++ b/container/implementations/ContainerGrinder.java @@ -0,0 +1,33 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotInaccessable; +import appeng.container.slot.SlotOutput; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.tile.grindstone.TileGrinder; + +public class ContainerGrinder extends AEBaseContainer +{ + + TileGrinder myte; + + public ContainerGrinder(InventoryPlayer ip, TileGrinder te) { + super( ip, te ); + myte = te; + + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.ORE, te, 0, 12, 17 ) ); + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.ORE, te, 1, 12 + 18, 17 ) ); + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.ORE, te, 2, 12 + 36, 17 ) ); + + addSlotToContainer( new SlotInaccessable( te, 6, 80, 40 ) ); + + addSlotToContainer( new SlotOutput( te, 3, 112, 63, 2 * 16 + 15 ) ); + addSlotToContainer( new SlotOutput( te, 4, 112 + 18, 63, 2 * 16 + 15 ) ); + addSlotToContainer( new SlotOutput( te, 5, 112 + 36, 63, 2 * 16 + 15 ) ); + + bindPlayerInventory( ip, 0, 176 - /* height of playerinventory */82 ); + } + +} diff --git a/container/implementations/ContainerLevelEmitter.java b/container/implementations/ContainerLevelEmitter.java new file mode 100644 index 00000000..14467ba5 --- /dev/null +++ b/container/implementations/ContainerLevelEmitter.java @@ -0,0 +1,23 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.container.AEBaseContainer; +import appeng.parts.automation.PartLevelEmitter; + +public class ContainerLevelEmitter extends AEBaseContainer +{ + + PartLevelEmitter myte; + + public ContainerLevelEmitter(InventoryPlayer ip, PartLevelEmitter te) { + super( ip, te.getHost().getTile() ); + myte = te; + + // addSlotToContainer( new SlotRestrictedInput( + // PlaceableItemType.WIRELESS_TERMINAL, te, 0, 71, 14 ) ); + // addSlotToContainer( new SlotOutput( te, 1, 71, 14, + // PlaceableItemType.WIRELESS_TERMINAL.icon ) ); + + bindPlayerInventory( ip, 0, 199 - /* height of playerinventory */82 ); + } +} diff --git a/container/implementations/ContainerMEMonitorable.java b/container/implementations/ContainerMEMonitorable.java new file mode 100644 index 00000000..764ecb94 --- /dev/null +++ b/container/implementations/ContainerMEMonitorable.java @@ -0,0 +1,166 @@ +package appeng.container.implementations; + +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ICrafting; +import net.minecraft.network.packet.Packet; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IMEChest; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMontorHandlerReciever; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.container.AEBaseContainer; +import appeng.core.sync.packets.PacketMEInventoryUpdate; +import appeng.util.Platform; +import appeng.util.item.ItemList; +import cpw.mods.fml.common.network.PacketDispatcher; +import cpw.mods.fml.common.network.Player; + +public class ContainerMEMonitorable extends AEBaseContainer implements IMEMontorHandlerReciever +{ + + final IMEMonitor monitor; + final IItemList items = new ItemList(); + + public ContainerMEMonitorable(InventoryPlayer ip, IStorageMonitorable montiorable) { + super( ip, montiorable instanceof TileEntity ? (TileEntity) montiorable : null ); + + if ( Platform.isServer() ) + { + monitor = montiorable.getItemInventory(); + monitor.addListener( this, null ); + + cellInv = monitor; + if ( montiorable instanceof IMEChest ) + powerSrc = (IMEChest) montiorable; + else if ( montiorable instanceof IGridHost ) + { + IGridNode node = ((IGridHost) montiorable).getGridNode( ForgeDirection.UNKNOWN ); + if ( node != null ) + { + IGrid g = node.getGrid(); + if ( g != null ) + powerSrc = g.getCache( IEnergyGrid.class ); + } + } + } + else + monitor = null; + + bindPlayerInventory( ip, 0, 0 ); + } + + @Override + public void detectAndSendChanges() + { + if ( Platform.isServer() ) + { + if ( !items.isEmpty() ) + { + try + { + IItemList monitorCache = monitor.getStorageList(); + + PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); + + for (IAEItemStack is : items) + { + IAEItemStack send = monitorCache.findPrecise( is ); + if ( send == null ) + { + is.setStackSize( 0 ); + piu.appendItem( is ); + } + else + piu.appendItem( send ); + } + + if ( !piu.isEmpty() ) + { + Packet p = piu.getPacket(); + items.resetStatus(); + + for (Object c : this.crafters) + { + if ( c instanceof Player ) + PacketDispatcher.sendPacketToPlayer( p, (Player) c ); + } + } + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + super.detectAndSendChanges(); + } + } + + @Override + public void addCraftingToCrafters(ICrafting c) + { + super.addCraftingToCrafters( c ); + + if ( Platform.isServer() && c instanceof Player ) + { + try + { + PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); + IItemList monitorCache = monitor.getStorageList(); + + for (IAEItemStack send : monitorCache) + { + piu.appendItem( send ); + } + + Packet p = piu.getPacket(); + PacketDispatcher.sendPacketToPlayer( p, (Player) c ); + } + catch (IOException e) + { + e.printStackTrace(); + } + + } + } + + @Override + public void onContainerClosed(EntityPlayer player) + { + super.onContainerClosed( player ); + if ( monitor != null ) + monitor.removeListener( this ); + } + + @Override + public void removeCraftingFromCrafters(ICrafting c) + { + super.removeCraftingFromCrafters( c ); + + if ( this.crafters.isEmpty() ) + monitor.removeListener( this ); + } + + @Override + public void postChange(IAEItemStack change) + { + items.add( change ); + } + + @Override + public boolean isValid(Object verificationToken) + { + return true; + } + +} diff --git a/container/implementations/ContainerNetworkStatus.java b/container/implementations/ContainerNetworkStatus.java new file mode 100644 index 00000000..f051865a --- /dev/null +++ b/container/implementations/ContainerNetworkStatus.java @@ -0,0 +1,24 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.tileentity.TileEntity; +import appeng.container.AEBaseContainer; + +public class ContainerNetworkStatus extends AEBaseContainer +{ + + TileEntity myte; + + public ContainerNetworkStatus(InventoryPlayer ip, TileEntity te) { + super( ip, (TileEntity) te ); + myte = te; + + // addSlotToContainer( new SlotRestrictedInput( + // PlaceableItemType.WIRELESS_TERMINAL, te, 0, 71, 14 ) ); + // addSlotToContainer( new SlotOutput( te, 1, 71, 14, + // PlaceableItemType.WIRELESS_TERMINAL.icon ) ); + + bindPlayerInventory( ip, 0, 199 - /* height of playerinventory */82 ); + } + +} diff --git a/container/implementations/ContainerSpatialIOPort.java b/container/implementations/ContainerSpatialIOPort.java new file mode 100644 index 00000000..b84dbd41 --- /dev/null +++ b/container/implementations/ContainerSpatialIOPort.java @@ -0,0 +1,25 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotOutput; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.tile.spatial.TileSpatialIOPort; + +public class ContainerSpatialIOPort extends AEBaseContainer +{ + + TileSpatialIOPort myte; + + public ContainerSpatialIOPort(InventoryPlayer ip, TileSpatialIOPort te) { + super( ip, te ); + myte = te; + + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.SPATIAL_STORAGE_CELLS, te, 0, 71, 14 ) ); + addSlotToContainer( new SlotOutput( te, 1, 71, 14, PlaceableItemType.SPATIAL_STORAGE_CELLS.icon ) ); + + bindPlayerInventory( ip, 0, 199 - /* height of playerinventory */82 ); + } + +} diff --git a/container/implementations/ContainerVibrationChamber.java b/container/implementations/ContainerVibrationChamber.java new file mode 100644 index 00000000..cc9e2db3 --- /dev/null +++ b/container/implementations/ContainerVibrationChamber.java @@ -0,0 +1,78 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ICrafting; +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotRestrictedInput; +import appeng.container.slot.SlotRestrictedInput.PlaceableItemType; +import appeng.core.AELog; +import appeng.tile.misc.TileVibrationChamber; +import appeng.util.Platform; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ContainerVibrationChamber extends AEBaseContainer +{ + + TileVibrationChamber myte; + + public ContainerVibrationChamber(InventoryPlayer ip, TileVibrationChamber te) { + super( ip, te ); + myte = te; + + addSlotToContainer( new SlotRestrictedInput( PlaceableItemType.FUEL, te, 0, 80, 37 ) ); + + bindPlayerInventory( ip, 0, 166 - /* height of playerinventory */82 ); + } + + public int aePerTick = 5; + public int burnSpeed = 100; + public int burnProgress = 0; + + @Override + public void detectAndSendChanges() + { + super.detectAndSendChanges(); + + if ( Platform.isServer() ) + { + int burnProgress = (int) (this.myte.maxBurnTime <= 0 ? 0 : 12 * this.myte.burnTime / this.myte.maxBurnTime); + + for (int i = 0; i < this.crafters.size(); ++i) + { + ICrafting icrafting = (ICrafting) this.crafters.get( i ); + + if ( this.burnProgress != burnProgress ) + { + icrafting.sendProgressBarUpdate( this, 0, (int) burnProgress ); + } + + if ( this.burnSpeed != this.myte.burnSpeed ) + { + AELog.info( "" + this.myte.burnSpeed ); + icrafting.sendProgressBarUpdate( this, 1, this.myte.burnSpeed ); + } + } + + this.burnProgress = burnProgress; + this.burnSpeed = this.myte.burnSpeed; + } + } + + @Override + @SideOnly(Side.CLIENT) + public void updateProgressBar(int idx, int value) + { + if ( idx == 0 ) + { + this.burnProgress = value; + } + + if ( idx == 1 ) + { + this.burnSpeed = value; + } + + } + +} diff --git a/container/slot/AppEngCraftingSlot.java b/container/slot/AppEngCraftingSlot.java new file mode 100644 index 00000000..e2d8405e --- /dev/null +++ b/container/slot/AppEngCraftingSlot.java @@ -0,0 +1,15 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.SlotCrafting; + +public class AppEngCraftingSlot extends SlotCrafting +{ + + public AppEngCraftingSlot(EntityPlayer par1EntityPlayer, IInventory par2iInventory, IInventory par3iInventory, int par4, + int par5, int par6) { + super( par1EntityPlayer, par2iInventory, par3iInventory, par4, par5, par6 ); + } + +} diff --git a/container/slot/AppEngSlot.java b/container/slot/AppEngSlot.java new file mode 100644 index 00000000..819740d4 --- /dev/null +++ b/container/slot/AppEngSlot.java @@ -0,0 +1,71 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class AppEngSlot extends Slot +{ + + public enum hasCalculatedValidness + { + NotAvailable, Valid, Invalid + }; + + public int icon = -1; + public hasCalculatedValidness isValid; + public int defX, defY; + + public String getTooltip() + { + return null; + } + + @Override + public void onSlotChanged() + { + super.onSlotChanged(); + isValid = hasCalculatedValidness.NotAvailable; + } + + public AppEngSlot(IInventory inv, int idx, int x, int y) { + super( inv, idx, x, y ); + defX = x; + defY = y; + isValid = hasCalculatedValidness.NotAvailable; + } + + public boolean isDisplay = false; + + @Override + public ItemStack getStack() + { + if ( isDisplay ) + { + isDisplay = false; + return getDisplayStack(); + } + return super.getStack(); + } + + public ItemStack getDisplayStack() + { + return super.getStack(); + } + + public float getOpacityOfIcon() + { + return 0.4f; + } + + public boolean renderIconWithItem() + { + return false; + } + + public int getIcon() + { + return icon; + } + +} diff --git a/container/slot/ISlotPlayerSide.java b/container/slot/ISlotPlayerSide.java new file mode 100644 index 00000000..9b4b9402 --- /dev/null +++ b/container/slot/ISlotPlayerSide.java @@ -0,0 +1,8 @@ +package appeng.container.slot; + +// anything that implements this interface is treated as being part of the players interface, rather then the chests... + +public interface ISlotPlayerSide +{ + +} diff --git a/container/slot/NullSlot.java b/container/slot/NullSlot.java new file mode 100644 index 00000000..d6e55c77 --- /dev/null +++ b/container/slot/NullSlot.java @@ -0,0 +1,80 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class NullSlot extends Slot +{ + + public NullSlot() { + super( null, 0, 0, 0 ); + } + + @Override + public void onSlotChange(ItemStack par1ItemStack, ItemStack par2ItemStack) + { + + } + + @Override + public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) + { + + } + + @Override + public boolean isItemValid(ItemStack par1ItemStack) + { + return false; + } + + @Override + public ItemStack getStack() + { + return null; + } + + @Override + public void putStack(ItemStack par1ItemStack) + { + + } + + @Override + public void onSlotChanged() + { + + } + + @Override + public int getSlotStackLimit() + { + return 0; + } + + @Override + public ItemStack decrStackSize(int par1) + { + return null; + } + + @Override + public boolean isSlotInInventory(IInventory par1IInventory, int par2) + { + return false; + } + + @Override + public boolean canTakeStack(EntityPlayer par1EntityPlayer) + { + return false; + } + + @Override + public int getSlotIndex() + { + return 0; + } +} diff --git a/container/slot/SlotCraftingMatrix.java b/container/slot/SlotCraftingMatrix.java new file mode 100644 index 00000000..3a4ced25 --- /dev/null +++ b/container/slot/SlotCraftingMatrix.java @@ -0,0 +1,12 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; + +public class SlotCraftingMatrix extends AppEngSlot +{ + + public SlotCraftingMatrix(IInventory par1iInventory, int par2, int par3, int par4) { + super( par1iInventory, par2, par3, par4 ); + } + +} diff --git a/container/slot/SlotDisabled.java b/container/slot/SlotDisabled.java new file mode 100644 index 00000000..d6ed3b54 --- /dev/null +++ b/container/slot/SlotDisabled.java @@ -0,0 +1,25 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotDisabled extends AppEngSlot +{ + + public SlotDisabled(IInventory par1iInventory, int slotIndex, int x, int y) { + super( par1iInventory, slotIndex, x, y ); + } + + @Override + public boolean isItemValid(ItemStack par1ItemStack) + { + return false; + } + + @Override + public boolean canTakeStack(EntityPlayer par1EntityPlayer) + { + return false; + } +} diff --git a/container/slot/SlotFake.java b/container/slot/SlotFake.java new file mode 100644 index 00000000..6a547e03 --- /dev/null +++ b/container/slot/SlotFake.java @@ -0,0 +1,85 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import appeng.util.Platform; + +public class SlotFake extends AppEngSlot +{ + + int invSlot; + + public SlotFake(IInventory inv, int idx, int x, int y) { + super( inv, idx, x, y ); + invSlot = idx; + } + + public void addToInv(ItemStack is) + { + if ( is != null ) + { + ItemStack current = this.inventory.getStackInSlot( invSlot ); + + if ( current != null && Platform.isSameItem( current, is ) ) + { + current.stackSize += is.stackSize; + + if ( current.stackSize > inventory.getInventoryStackLimit() ) + current.stackSize = inventory.getInventoryStackLimit(); + } else + { + current = is.copy(); + + if ( current.stackSize > inventory.getInventoryStackLimit() ) + current.stackSize = inventory.getInventoryStackLimit(); + + this.inventory.setInventorySlotContents( invSlot, current ); + } + } else + { + this.inventory.setInventorySlotContents( invSlot, null ); + } + } + + @Override + public boolean canTakeStack(EntityPlayer par1EntityPlayer) + { + return false; + } + + @Override + public ItemStack decrStackSize(int par1) + { + ItemStack current = this.inventory.getStackInSlot( invSlot ); + + if ( current != null ) + { + current.stackSize--; + + if ( current.stackSize <= 0 ) + { + this.inventory.setInventorySlotContents( invSlot, null ); + } + } + + return null; + } + + @Override + public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) + { + } + + @Override + public void putStack(ItemStack par1ItemStack) + { + this.inventory.setInventorySlotContents( invSlot, par1ItemStack ); + } + + @Override + public boolean isItemValid(ItemStack par1ItemStack) + { + return true; + } +} diff --git a/container/slot/SlotFakeBlacklist.java b/container/slot/SlotFakeBlacklist.java new file mode 100644 index 00000000..6ca8bf84 --- /dev/null +++ b/container/slot/SlotFakeBlacklist.java @@ -0,0 +1,34 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; + +public class SlotFakeBlacklist extends SlotFakeTypeOnly +{ + + public SlotFakeBlacklist(IInventory inv, int idx, int x, int y) { + super( inv, idx, x, y ); + } + + @Override + public boolean renderIconWithItem() + { + return true; + } + + @Override + public float getOpacityOfIcon() + { + return 0.8f; + } + + @Override + public int getIcon() + { + if ( getHasStack() ) + { + return getStack().stackSize > 0 ? 16 + 14 : 14; + } + return -1; + } + +} diff --git a/container/slot/SlotFakeTypeOnly.java b/container/slot/SlotFakeTypeOnly.java new file mode 100644 index 00000000..1a132b8a --- /dev/null +++ b/container/slot/SlotFakeTypeOnly.java @@ -0,0 +1,39 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotFakeTypeOnly extends SlotFake +{ + + public SlotFakeTypeOnly(IInventory inv, int idx, int x, int y) { + super( inv, idx, x, y ); + } + + @Override + public void addToInv(ItemStack is) + { + if ( is != null ) + { + is = is.copy(); + is.stackSize = 1; + } + + super.putStack( is ); + } + + @Override + public void putStack(ItemStack is) + { + if ( is != null ) + { + is = is.copy(); + if ( is.stackSize > 1 ) + is.stackSize = 1; + else if ( is.stackSize < -1 ) + is.stackSize = -1; + } + + super.putStack( is ); + } +} diff --git a/container/slot/SlotInaccessable.java b/container/slot/SlotInaccessable.java new file mode 100644 index 00000000..5424b0ad --- /dev/null +++ b/container/slot/SlotInaccessable.java @@ -0,0 +1,47 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotInaccessable extends AppEngSlot +{ + + public SlotInaccessable(IInventory i, int slotIdx, int x, int y) { + super( i, slotIdx, x, y ); + } + + ItemStack dspStack = null; + + @Override + public ItemStack getDisplayStack() + { + if ( dspStack == null ) + { + ItemStack dsp = super.getDisplayStack(); + if ( dsp != null ) + dspStack = dsp.copy(); + } + return dspStack; + } + + @Override + public void onSlotChanged() + { + super.onSlotChanged(); + dspStack = null; + } + + @Override + public boolean canTakeStack(EntityPlayer par1EntityPlayer) + { + return false; + } + + @Override + public boolean isItemValid(ItemStack i) + { + return false; + } + +} diff --git a/container/slot/SlotInaccessableHD.java b/container/slot/SlotInaccessableHD.java new file mode 100644 index 00000000..3fc72a3b --- /dev/null +++ b/container/slot/SlotInaccessableHD.java @@ -0,0 +1,12 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; + +public class SlotInaccessableHD extends SlotInaccessable +{ + + public SlotInaccessableHD(IInventory i, int slotIdx, int x, int y) { + super( i, slotIdx, x, y ); + } + +} diff --git a/container/slot/SlotNormal.java b/container/slot/SlotNormal.java new file mode 100644 index 00000000..4d3d5b92 --- /dev/null +++ b/container/slot/SlotNormal.java @@ -0,0 +1,14 @@ +package appeng.container.slot; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; + +public class SlotNormal extends AppEngSlot +{ + + public SlotNormal(Container _c, EntityPlayer _p, IInventory par1iInventory, int par2, int par3, int par4) { + super( par1iInventory, par2, par3, par4 ); + } + +} diff --git a/container/slot/SlotOutput.java b/container/slot/SlotOutput.java new file mode 100644 index 00000000..4f7da7bd --- /dev/null +++ b/container/slot/SlotOutput.java @@ -0,0 +1,19 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotOutput extends AppEngSlot +{ + + public SlotOutput(IInventory a, int b, int c, int d, int i) { + super( a, b, c, d ); + icon = i; + } + + @Override + public boolean isItemValid(ItemStack i) + { + return false; + } +} diff --git a/container/slot/SlotPlayerHotBar.java b/container/slot/SlotPlayerHotBar.java new file mode 100644 index 00000000..c080b5bc --- /dev/null +++ b/container/slot/SlotPlayerHotBar.java @@ -0,0 +1,11 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; + +public class SlotPlayerHotBar extends AppEngSlot implements ISlotPlayerSide +{ + + public SlotPlayerHotBar(IInventory par1iInventory, int par2, int par3, int par4) { + super( par1iInventory, par2, par3, par4 ); + } +} diff --git a/container/slot/SlotPlayerInv.java b/container/slot/SlotPlayerInv.java new file mode 100644 index 00000000..320b6928 --- /dev/null +++ b/container/slot/SlotPlayerInv.java @@ -0,0 +1,13 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; + +// there is nothing special about this slot, its simply used to represent the players inventory, vs a container slot. + +public class SlotPlayerInv extends AppEngSlot implements ISlotPlayerSide +{ + + public SlotPlayerInv(IInventory par1iInventory, int par2, int par3, int par4) { + super( par1iInventory, par2, par3, par4 ); + } +} diff --git a/container/slot/SlotRestrictedInput.java b/container/slot/SlotRestrictedInput.java new file mode 100644 index 00000000..df7a7c4b --- /dev/null +++ b/container/slot/SlotRestrictedInput.java @@ -0,0 +1,140 @@ +package appeng.container.slot; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.api.IAppEngApi; +import appeng.api.crafting.ICraftingPatternMAC; +import appeng.api.implementations.ICraftingPatternItem; +import appeng.api.implementations.ISpatialStorageCell; +import appeng.api.implementations.IStorageComponent; +import appeng.util.Platform; + +public class SlotRestrictedInput extends AppEngSlot +{ + + public enum PlaceableItemType + { + STORAGE_CELLS(15), ORE(1 * 16 + 15), STORAGE_COMPONENT(3 * 16 + 15), WIRELESS_TERMINAL(4 * 16 + 15), TRASH(5 * 16 + 15), VALID_ENCODED_PATTERN_W_OUPUT(7 * 16 + 15), ENCODED_PATTERN_W_OUTPUT( + 7 * 16 + 15), ENCODED_PATTERN(7 * 16 + 15), BLANK_PATTERN(8 * 16 + 15), POWERED_TOOL(9 * 16 + 15), RANGE_BOOSTER(6 * 16 + 15), QE_SINGULARTIY(10 * 16 + 15), SPATIAL_STORAGE_CELLS( + 11 * 16 + 15), FUEL(12 * 16 + 15); + + public final int icon; + + private PlaceableItemType(int o) { + icon = o; + } + }; + + @Override + public int getSlotStackLimit() + { + if ( stackLimit != -1 ) + return stackLimit; + return super.getSlotStackLimit(); + } + + public boolean isValid(ItemStack is, World theWorld) + { + if ( which == PlaceableItemType.VALID_ENCODED_PATTERN_W_OUPUT ) + { + ICraftingPatternMAC ap = is.getItem() instanceof ICraftingPatternItem ? ((ICraftingPatternItem) is.getItem()).getPatternForItem( is ) : null; + if ( ap != null && ap.isEncoded() && ap.isCraftable( theWorld ) ) + return true; + return false; + } + return true; + } + + public PlaceableItemType which; + public int stackLimit = -1; + + public Slot setStackLimit(int i) + { + stackLimit = i; + return this; + } + + public SlotRestrictedInput(PlaceableItemType valid, IInventory i, int slotnum, int x, int y) { + super( i, slotnum, x, y ); + which = valid; + icon = valid.icon; + } + + @Override + public ItemStack getDisplayStack() + { + if ( Platform.isClient() && (which == PlaceableItemType.VALID_ENCODED_PATTERN_W_OUPUT || which == PlaceableItemType.ENCODED_PATTERN_W_OUTPUT) ) + { + ItemStack is = super.getStack(); + if ( is != null ) + { + ICraftingPatternMAC ap = is.getItem() instanceof ICraftingPatternItem ? ((ICraftingPatternItem) is.getItem()).getPatternForItem( is ) : null; + if ( ap != null ) + { + return ap.getOutput().getItemStack(); + } + } + } + return super.getStack(); + } + + @Override + public boolean isItemValid(ItemStack i) + { + if ( i == null ) + return false; + if ( i.getItem() == null ) + return false; + + IAppEngApi api = AEApi.instance(); + switch (which) + { + case VALID_ENCODED_PATTERN_W_OUPUT: + case ENCODED_PATTERN_W_OUTPUT: + case ENCODED_PATTERN: { + ICraftingPatternMAC pattern = i.getItem() instanceof ICraftingPatternItem ? ((ICraftingPatternItem) i.getItem()).getPatternForItem( i ) : null; + if ( pattern != null ) + return pattern.isEncoded(); + return false; + } + case BLANK_PATTERN: { + ICraftingPatternMAC pattern = i.getItem() instanceof ICraftingPatternItem ? ((ICraftingPatternItem) i.getItem()).getPatternForItem( i ) : null; + if ( pattern != null ) + return !pattern.isEncoded(); + + return false; + } + case ORE: + return appeng.api.AEApi.instance().registries().grinder().getRecipeForInput( i ) != null; + case FUEL: + return TileEntityFurnace.getItemBurnTime( i ) > 0; + case POWERED_TOOL: + return Platform.isChargeable( i ); + case QE_SINGULARTIY: + return api.materials().materialQESingularity.sameAs( i ); + case RANGE_BOOSTER: + return api.materials().materialWirelessBooster.sameAs( i ); + case SPATIAL_STORAGE_CELLS: + return i.getItem() instanceof ISpatialStorageCell && ((ISpatialStorageCell) i.getItem()).isSpatialStorage( i ); + case STORAGE_CELLS: + return AEApi.instance().registries().cell().isCellHandled( i ); + case STORAGE_COMPONENT: + boolean isComp = i.getItem() instanceof IStorageComponent && ((IStorageComponent) i.getItem()).isStorageComponent( i ); + return isComp; + case TRASH: + if ( AEApi.instance().registries().cell().isCellHandled( i ) ) + return false; + if ( i.getItem() instanceof IStorageComponent && ((IStorageComponent) i.getItem()).isStorageComponent( i ) ) + return false; + return true; + case WIRELESS_TERMINAL: + return AEApi.instance().registries().wireless().isWirelessTerminal( i ); + } + + return false; + } +} diff --git a/core/AELog.java b/core/AELog.java new file mode 100644 index 00000000..c07caec9 --- /dev/null +++ b/core/AELog.java @@ -0,0 +1,54 @@ +package appeng.core; + +import java.io.File; +import java.util.logging.Level; + +import cpw.mods.fml.relauncher.FMLRelaunchLog; + +public class AELog +{ + + public static cpw.mods.fml.relauncher.FMLRelaunchLog instance = cpw.mods.fml.relauncher.FMLRelaunchLog.log; + public static net.minecraftforge.common.Configuration localizeation = new net.minecraftforge.common.Configuration( new File( "en_us.lang" ) ); + + private AELog() { + } + + private static void log(Level level, String format, Object... data) + { + FMLRelaunchLog.log( "AE", level, format, data ); + } + + public static void severe(String format, Object... data) + { + log( Level.SEVERE, format, data ); + } + + public static void warning(String format, Object... data) + { + log( Level.WARNING, format, data ); + } + + public static void info(String format, Object... data) + { + log( Level.INFO, format, data ); + } + + public static void grinder(String o) + { + log( Level.FINEST, "grinder: " + o ); + } + + public static void localization(String category, String unlocalizedName) + { + localizeation.get( category, unlocalizedName, unlocalizedName ); + localizeation.save(); + } + + public static void error(Throwable e) + { + log( Level.SEVERE, "Error Occurred" ); + e.printStackTrace(); + } + +} diff --git a/core/Api.java b/core/Api.java new file mode 100644 index 00000000..a8cd3fba --- /dev/null +++ b/core/Api.java @@ -0,0 +1,96 @@ +package appeng.core; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.IAppEngApi; +import appeng.api.definitions.Blocks; +import appeng.api.definitions.Items; +import appeng.api.definitions.Materials; +import appeng.api.definitions.Parts; +import appeng.api.features.IRegistryContainer; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IPartHelper; +import appeng.api.storage.IStorageHelper; +import appeng.core.api.ApiPart; +import appeng.core.api.ApiStorage; +import appeng.core.features.registries.RegistryContainer; +import appeng.me.GridConnection; +import appeng.me.GridNode; +import appeng.util.Platform; + +public class Api implements IAppEngApi +{ + + public static final Api instance = new Api(); + + private Api() { + + } + + // private MovableTileRegistry MovableRegistry = new MovableTileRegistry(); + private RegistryContainer rc = new RegistryContainer(); + private ApiStorage storageHelper = new ApiStorage(); + public ApiPart partHelper = new ApiPart(); + + private Materials materials = new Materials(); + private Items items = new Items(); + private Blocks blocks = new Blocks(); + private Parts parts = new Parts(); + + @Override + public IRegistryContainer registries() + { + return rc; + } + + @Override + public Items items() + { + return items; + } + + @Override + public Materials materials() + { + return materials; + } + + @Override + public Blocks blocks() + { + return blocks; + } + + @Override + public Parts parts() + { + return parts; + } + + @Override + public IStorageHelper storage() + { + return storageHelper; + } + + @Override + public IPartHelper partHelper() + { + return partHelper; + } + + @Override + public IGridNode createGridNode(IGridBlock blk) + { + if ( Platform.isClient() ) + throw new RuntimeException( "Grid Features are Server Side Only." ); + return new GridNode( blk ); + } + + @Override + public IGridConnection createGridConnection(IGridNode a, IGridNode b) + { + return new GridConnection( a, b, ForgeDirection.UNKNOWN ); + } +} diff --git a/core/AppEng.java b/core/AppEng.java new file mode 100644 index 00000000..54b61541 --- /dev/null +++ b/core/AppEng.java @@ -0,0 +1,169 @@ +package appeng.core; + +import net.minecraft.item.ItemStack; +import appeng.core.crash.CrashEnhancement; +import appeng.core.crash.CrashInfo; +import appeng.core.features.AEFeature; +import appeng.core.sync.AppEngClientPacketHandler; +import appeng.core.sync.AppEngServerPacketHandler; +import appeng.helpers.TickHandler; +import appeng.integration.IntegrationRegistry; +import appeng.integration.IntegrationSide; +import appeng.server.AECommand; +import appeng.services.Profiler; +import appeng.services.VersionChecker; +import appeng.util.Platform; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.common.network.NetworkMod; +import cpw.mods.fml.common.network.NetworkMod.SidedPacketHandler; + +@Mod(modid = AppEng.modid, name = AppEng.name, version = Configuration.VERSION, dependencies = AppEng.dependencies) +@NetworkMod(clientSideRequired = true, serverSideRequired = true, clientPacketHandlerSpec = @SidedPacketHandler(channels = { Configuration.PACKET_CHANNEL }, packetHandler = AppEngClientPacketHandler.class), serverPacketHandlerSpec = @SidedPacketHandler(channels = (Configuration.PACKET_CHANNEL), packetHandler = AppEngServerPacketHandler.class)) +public class AppEng +{ + + public final static String modid = "appliedenergistics2"; + public final static String name = "Applied Energistics 2"; + + public static AppEng instance; + + public final static String dependencies = + + // a few mods, AE should load after, probably. + // required-after:AppliedEnergistics2API|all; + "after:gregtech_addon;after:Mekanism;after:IC2;after:ThermalExpansion;after:BuildCraft|Core;" + + + // depend on version of forge used for build. + "required-after:Forge@[" // require forge. + + net.minecraftforge.common.ForgeVersion.majorVersion + "." // majorVersion + + net.minecraftforge.common.ForgeVersion.minorVersion + "." // minorVersion + + net.minecraftforge.common.ForgeVersion.revisionVersion + "." // revisionVersion + + net.minecraftforge.common.ForgeVersion.buildVersion + ",)"; // buildVersion + + public AppEng() { + + instance = this; + + for (CrashInfo ci : CrashInfo.values()) + FMLCommonHandler.instance().registerCrashCallable( new CrashEnhancement( ci ) ); + + // detect funny obfuscation issues? + try + { + new ItemStack( 1, 1, 0 ).getItemDamage(); + } + catch (Throwable t) + { + throw new Error( "AE2 is incompatible with this environment, please verify your using the correct version of AE2." ); + } + + } + + private IntegrationRegistry integrationModules = new IntegrationRegistry( new Object[] { + + /** + * Display Name, ModID ClassPostFix + */ + IntegrationSide.BOTH, "Industrial Craft 2", "IC2", "IC2", // IC2 + IntegrationSide.BOTH, "Railcraft", "Railcraft", "RC", // RC + IntegrationSide.BOTH, "Thermal Expansion", "ThermalExpansion", "TE", // TE + IntegrationSide.BOTH, "Mystcraft", "Mystcraft", "Mystcraft", // MC + IntegrationSide.BOTH, "BuildCraft", "BuildCraft|Silicon", "BC", // BC + IntegrationSide.BOTH, "Greg Tech", "gregtech_addon", "GT", // GT + IntegrationSide.BOTH, "Universal Electricity", null, "UE", // UE + IntegrationSide.BOTH, "Logistics Pipes", "LogisticsPipes|Main", "LP", // LP + // IntegrationSide.CLIENT, "Inventory Tweaks", "", "InvTweaks", + IntegrationSide.BOTH, "Mine Factory Reloaded", "MineFactoryReloaded", "MFR", // MFR + IntegrationSide.BOTH, "Better Storage", "betterstorage", "BS", // BS + IntegrationSide.BOTH, "Factorization", "factorization", "FZ", // FZ + IntegrationSide.BOTH, "Forestry", "Forestry", "Forestry", // Forestry + IntegrationSide.BOTH, "Mekanism", "Mekanism", "Mekanism", // MeK + IntegrationSide.CLIENT, "Not Enought Items", "NotEnoughItems", "NEI", // Not Eneough Items + IntegrationSide.BOTH, "Forge MultiPart", "McMultipart", "FMP" } ); + + public boolean isIntegrationEnabled(String Name) + { + return integrationModules.isEnabled( Name ); + } + + public Object getIntegration(String Name) + { + return integrationModules.getInstance( Name ); + } + + @EventHandler + void PreInit(FMLPreInitializationEvent event) + { + AELog.info( "Starting ( PreInit )" ); + + Configuration.instance = new Configuration( event.getSuggestedConfigurationFile() ); + + if ( Platform.isClient() ) + { + CreativeTab.init(); + CommonHelper.proxy.init(); + } + + Registration.instance.PreInit( event ); + + if ( Configuration.instance.isFeatureEnabled( AEFeature.Profiler ) ) + { + AELog.info( "Starting Profiler" ); + (new Thread( Profiler.instance = new Profiler() )).start(); + } + + if ( Configuration.instance.isFeatureEnabled( AEFeature.VersionChecker ) ) + { + AELog.info( "Starting VersionChecker" ); + (new Thread( VersionChecker.instance = new VersionChecker() )).start(); + } + + AELog.info( "PreInit ( end )" ); + } + + @EventHandler + void Init(FMLInitializationEvent event) + { + AELog.info( "Init" ); + + Registration.instance.Init( event ); + integrationModules.init(); + + AELog.info( "Init ( end )" ); + } + + @EventHandler + void PostInit(FMLPostInitializationEvent event) + { + AELog.info( "PostInit" ); + + Registration.instance.PostInit( event ); + integrationModules.postinit(); + + Configuration.instance.save(); + + AELog.info( "PostInit ( end )" ); + } + + @EventHandler + public void serverStopping(FMLServerStoppingEvent event) + { + WorldSettings.getInstance().shutdown(); + TickHandler.instance.shutdown(); + } + + @EventHandler + public void serverStarting(FMLServerStartingEvent evt) + { + WorldSettings.getInstance().init(); + evt.registerServerCommand( new AECommand( evt.getServer() ) ); + } + +} diff --git a/core/CommonHelper.java b/core/CommonHelper.java new file mode 100644 index 00000000..0609508c --- /dev/null +++ b/core/CommonHelper.java @@ -0,0 +1,27 @@ +package appeng.core; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.packet.Packet; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import cpw.mods.fml.common.SidedProxy; + +public abstract class CommonHelper +{ + + @SidedProxy(clientSide = "appeng.client.ClientHelper", serverSide = "appeng.server.ServerHelper") + public static CommonHelper proxy; + + public abstract void init(); + + public abstract World getWorld(); + + public abstract void bindTileEntitySpecialRenderer(Class tile, AEBaseBlock blk); + + public abstract List getPlayers(); + + public abstract void sendToAllNearExcept(EntityPlayer p, double x, double y, double z, double dist, World w, Packet packet); + +} diff --git a/core/Configuration.java b/core/Configuration.java new file mode 100644 index 00000000..7c3dcd07 --- /dev/null +++ b/core/Configuration.java @@ -0,0 +1,184 @@ +package appeng.core; + +import java.io.File; +import java.util.EnumSet; + +import appeng.api.config.CondenserOuput; +import appeng.api.config.PowerUnits; +import appeng.api.config.Settings; +import appeng.api.config.SortDir; +import appeng.api.config.SortOrder; +import appeng.api.config.YesNo; +import appeng.api.util.IConfigManager; +import appeng.api.util.IConfigureableObject; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.util.ConfigManager; +import appeng.util.IConfigManagerHost; + +public class Configuration extends net.minecraftforge.common.Configuration implements IConfigureableObject, IConfigManagerHost +{ + + public static Configuration instance; + + public String latestVersion = VERSION; + public long latestTimeStamp = 0; + + public static final String VERSION = "${version}"; + public static final String CHANNEL = "${channel}"; + + public final static String PACKET_CHANNEL = "AE"; + + public IConfigManager settings = new ConfigManager( this ); + public EnumSet featureFlags = EnumSet.noneOf( AEFeature.class ); + + public int oresPerCluster = 4; + + private double WirelessBaseCost = 8; + private double WirelessCostMultiplier = 1; + private double WirelessHighWirelessCount = 64; + + private double WirelessBaseRange = 16; + private double WirelessBoosterRangeMultiplier = 1; + private double WirelessBoosterExp = 1.5; + + public double wireless_getMaxRange(int boosters) + { + return WirelessBaseRange + WirelessBoosterRangeMultiplier * Math.pow( boosters, WirelessBoosterExp ); + } + + public double wireless_getPowerDrain(int boosters) + { + return WirelessBaseCost + WirelessCostMultiplier * Math.pow( boosters, 1 + boosters / WirelessHighWirelessCount ); + } + + public double spatialPowerScaler = 1.5; + public double spatialPowerMultiplier = 1500.0; + + private int blkBaseNumber = 900; + private int blkItemNumber = 3841; + + public String grinderOres[] = { + // Vanilla Items + "Obsidian", "EnderPearl", "Coal", "Iron", "Gold", "Charcoal", + // Common Mod Ores + "Copper", "Tin", "Silver", "Lead", "Bronze", + // Other Mod Ores + "Brass", "Platinum", "Nickel", "Invar", "Aluminium", "Electrum" }; + + public double oreDoublePercentage = 90.0; + + public boolean enableEffects = true; + public boolean enableNetworkProfiler = true; + + public Configuration(File f) { + super( f ); + + final double DEFAULT_BC_EXCHANGE = 5.0; + final double DEFAULT_UE_EXCHANGE = 5.0; + final double DEFAULT_IC2_EXCHANGE = 2.0; + final double DEFAULT_RTC_EXCHANGE = 1.0 / 11256.0; + final double DEFAULT_RF_EXCHANGE = 0.5; + + PowerUnits.MJ.conversionRatio = get( "PowerInputRatios", "BuildCraft", DEFAULT_BC_EXCHANGE ).getDouble( DEFAULT_BC_EXCHANGE ); + PowerUnits.KJ.conversionRatio = get( "PowerInputRatios", "UniversalElectricity", DEFAULT_UE_EXCHANGE ).getDouble( DEFAULT_UE_EXCHANGE ); + PowerUnits.EU.conversionRatio = get( "PowerInputRatios", "IC2", DEFAULT_IC2_EXCHANGE ).getDouble( DEFAULT_IC2_EXCHANGE ); + PowerUnits.WA.conversionRatio = get( "PowerInputRatios", "RotaryCraft", DEFAULT_RTC_EXCHANGE ).getDouble( DEFAULT_RTC_EXCHANGE ); + PowerUnits.RF.conversionRatio = get( "PowerInputRatios", "ThermalExpansion", DEFAULT_RF_EXCHANGE ).getDouble( DEFAULT_RF_EXCHANGE ); + + CondenserOuput.MATTER_BALLS.requiredPower = get( "Condenser", "MatterBalls", 256 ).getInt( 256 ); + CondenserOuput.SINGULARITY.requiredPower = get( "Condenser", "Singularity", 256000 ).getInt( 256000 ); + + grinderOres = get( "GrindStone", "grinderOres", grinderOres ).getStringList(); + oreDoublePercentage = get( "GrindStone", "oreDoublePercentage", oreDoublePercentage ).getDouble( oreDoublePercentage ); + enableEffects = get( "Client", "enableEffects", true ).getBoolean( true ); + enableNetworkProfiler = get( "Server", "enableNetworkProfiler", true ).getBoolean( true ); + + // settings.registerSetting( Settings.SEARCH_MODS, YesNo.YES ); + settings.registerSetting( Settings.SEARCH_TOOLTIPS, YesNo.YES ); + settings.registerSetting( Settings.SORT_BY, SortOrder.NAME ); + settings.registerSetting( Settings.SORT_DIRECTION, SortDir.ASCENDING ); + + for (AEFeature feature : AEFeature.values()) + { + if ( feature.isVisible() ) + { + if ( get( "Features." + feature.getCategory(), feature.name(), feature.defaultVaue() ).getBoolean( feature.defaultVaue() ) ) + featureFlags.add( feature ); + } + else + featureFlags.add( feature ); + } + + for (Enum e : settings.getSettings()) + { + String Category = e.getClass().getSimpleName(); + this.get( Category, e.name(), settings.getSetting( e ).name() ); + } + + if ( isFeatureEnabled( AEFeature.VersionChecker ) ) + { + try + { + latestVersion = get( "VersionChecker", "LatestVersion", "" ).getString(); + latestTimeStamp = Long.parseLong( get( "VersionChecker", "LatestTimeStamp", "" ).getString() ); + } + catch (NumberFormatException err) + { + latestTimeStamp = 0; + } + } + } + + @Override + public void updateSetting(Enum setting, Enum newValue) + { + for (Enum e : settings.getSettings()) + { + String Category = e.getClass().getSimpleName(); + this.get( Category, e.name(), settings.getSetting( e ).name() ); + } + + save(); + } + + @Override + public void save() + { + if ( isFeatureEnabled( AEFeature.VersionChecker ) ) + { + get( "VersionChecker", "LatestVersion", latestVersion ).set( latestVersion ); + get( "VersionChecker", "LatestTimeStamp", "" ).set( Long.toString( latestTimeStamp ) ); + } + + if ( hasChanged() ) + super.save(); + } + + @Override + public IConfigManager getConfigManager() + { + return settings; + } + + public boolean isFeatureEnabled(AEFeature f) + { + return featureFlags.contains( f ); + } + + public int getBlockID(Class c, String subname) + { + return getBlock( AEFeatureHandler.getName( c, subname ), blkBaseNumber++ ).getInt(); + } + + public int getItemID(Class c, String subname) + { + return getItem( AEFeatureHandler.getName( c, subname ), blkItemNumber++ ).getInt(); + } + + public boolean useTerminalUseLargeFont() + { + return false; + } + +} diff --git a/core/CreativeTab.java b/core/CreativeTab.java new file mode 100644 index 00000000..f0c5b859 --- /dev/null +++ b/core/CreativeTab.java @@ -0,0 +1,30 @@ +package appeng.core; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.util.Platform; + +public final class CreativeTab extends CreativeTabs +{ + + public static CreativeTab instance = null; + + public CreativeTab() { + super( "appliedenergistics2" ); + if ( Platform.isClient() ) + AELog.localization( "gui", "itemGroup." + getTabLabel() ); + } + + @Override + public ItemStack getIconItemStack() + { + return AEApi.instance().items().itemWirelessTerminal.stack( 1 ); + } + + public static void init() + { + instance = new CreativeTab(); + } + +} \ No newline at end of file diff --git a/core/Registration.java b/core/Registration.java new file mode 100644 index 00000000..3b5cb7bf --- /dev/null +++ b/core/Registration.java @@ -0,0 +1,350 @@ +package appeng.core; + +import ic2.api.energy.tile.IEnergySink; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.util.WeightedRandomChestContent; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.common.ChestGenHooks; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fluids.IFluidHandler; +import appeng.api.AEApi; +import appeng.api.definitions.Blocks; +import appeng.api.definitions.Items; +import appeng.api.definitions.Materials; +import appeng.api.definitions.Parts; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.pathing.IPathingGrid; +import appeng.api.networking.spatial.ISpatialCache; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.util.AEItemDefinition; +import appeng.block.grindstone.BlockCrank; +import appeng.block.grindstone.BlockGrinder; +import appeng.block.mac.BlockContainmentWall; +import appeng.block.mac.BlockCraftingAccelerator; +import appeng.block.mac.BlockHeatVent; +import appeng.block.mac.BlockPatternProvider; +import appeng.block.misc.BlockCharger; +import appeng.block.misc.BlockCondenser; +import appeng.block.misc.BlockInscriber; +import appeng.block.misc.BlockInterface; +import appeng.block.misc.BlockNetworkEmitter; +import appeng.block.misc.BlockPartitionEditor; +import appeng.block.misc.BlockQuartzCrystalizer; +import appeng.block.misc.BlockQuartzTorch; +import appeng.block.misc.BlockTinyTNT; +import appeng.block.misc.BlockVibrationChamber; +import appeng.block.networking.BlockCableBus; +import appeng.block.networking.BlockController; +import appeng.block.networking.BlockCreativeEnergyCell; +import appeng.block.networking.BlockDenseEnergyCell; +import appeng.block.networking.BlockEnergyAcceptor; +import appeng.block.networking.BlockEnergyCell; +import appeng.block.networking.BlockWireless; +import appeng.block.qnb.BlockQuantumLinkChamber; +import appeng.block.qnb.BlockQuantumRing; +import appeng.block.solids.BlockMatrixFrame; +import appeng.block.solids.BlockQuartz; +import appeng.block.solids.BlockQuartzChiseled; +import appeng.block.solids.BlockQuartzGlass; +import appeng.block.solids.BlockQuartzLamp; +import appeng.block.solids.BlockQuartzPillar; +import appeng.block.solids.OreQuartz; +import appeng.block.solids.OreQuartzCharged; +import appeng.block.spatial.BlockSpatialIOPort; +import appeng.block.spatial.BlockSpatialPylon; +import appeng.block.storage.BlockChest; +import appeng.block.storage.BlockDrive; +import appeng.block.storage.BlockIOPort; +import appeng.core.features.AEFeature; +import appeng.core.features.IAEFeature; +import appeng.core.features.registries.entries.BasicCellHandler; +import appeng.core.features.registries.entries.CreativeCellHandler; +import appeng.core.localization.GuiText; +import appeng.core.localization.PlayerMessages; +import appeng.core.sync.GuiBridge; +import appeng.debug.ToolDebugCard; +import appeng.helpers.AETrading; +import appeng.helpers.PartPlacement; +import appeng.helpers.QuartzWorldGen; +import appeng.helpers.TickHandler; +import appeng.items.ItemEncodedPattern; +import appeng.items.materials.ItemMaterial; +import appeng.items.materials.MaterialType; +import appeng.items.parts.ItemFacade; +import appeng.items.parts.ItemPart; +import appeng.items.parts.PartType; +import appeng.items.storage.ItemBasicStorageCell; +import appeng.items.storage.ItemCreativeStorageCell; +import appeng.items.storage.ItemSpatialStorageCell; +import appeng.items.tools.ToolMemoryCard; +import appeng.items.tools.powered.ToolChargedStaff; +import appeng.items.tools.powered.ToolEntropyManipulator; +import appeng.items.tools.powered.ToolMassCannon; +import appeng.items.tools.powered.ToolWirelessTerminal; +import appeng.items.tools.quartz.ToolQuartzAxe; +import appeng.items.tools.quartz.ToolQuartzCuttingKnife; +import appeng.items.tools.quartz.ToolQuartzHoe; +import appeng.items.tools.quartz.ToolQuartzPickaxe; +import appeng.items.tools.quartz.ToolQuartzSpade; +import appeng.items.tools.quartz.ToolQuartzSword; +import appeng.items.tools.quartz.ToolQuartzWrench; +import appeng.me.cache.EnergyGridCache; +import appeng.me.cache.GridStorageCache; +import appeng.me.cache.P2PCache; +import appeng.me.cache.PathGridCache; +import appeng.me.cache.SpatialPylonCache; +import appeng.me.cache.TickManagerCache; +import appeng.me.storage.AEExternalHandler; +import appeng.recipes.ores.OreDictionaryHandler; +import buildcraft.api.power.IPowerEmitter; +import buildcraft.api.power.IPowerReceptor; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.common.registry.TickRegistry; +import cpw.mods.fml.common.registry.VillagerRegistry; +import cpw.mods.fml.relauncher.Side; + +public class Registration +{ + + final public static Registration instance = new Registration(); + + public BiomeGenBase storageBiome; + + private Registration() { + } + + final private Multimap featuresToEntities = ArrayListMultimap.create(); + + public void PreInit(FMLPreInitializationEvent event) + { + MinecraftForge.EVENT_BUS.register( OreDictionaryHandler.instance ); + + Items items = AEApi.instance().items(); + Materials materials = AEApi.instance().materials(); + Parts parts = AEApi.instance().parts(); + Blocks blocks = AEApi.instance().blocks(); + + Class materialClass = materials.getClass(); + for (MaterialType mat : MaterialType.values()) + { + try + { + Field f = materialClass.getField( "material" + mat.name() ); + f.set( materials, addFeature( ItemMaterial.class, mat ) ); + } + catch (Throwable err) + { + AELog.severe( "Error creating material: " + mat.name() ); + throw new RuntimeException( err ); + } + } + + Class partClass = parts.getClass(); + for (PartType part : PartType.values()) + { + try + { + Field f = partClass.getField( "part" + part.name() ); + f.set( parts, addFeature( ItemPart.class, part ) ); + } + catch (Throwable err) + { + AELog.severe( "Error creating part: " + part.name() ); + throw new RuntimeException( err ); + } + } + + // very important block! + blocks.blockMultiPart = addFeature( BlockCableBus.class ); + + blocks.blockQuartzOre = addFeature( OreQuartz.class ); + blocks.blockQuartzOreCharged = addFeature( OreQuartzCharged.class ); + blocks.blockMatrixFrame = addFeature( BlockMatrixFrame.class ); + blocks.blockQuartz = addFeature( BlockQuartz.class ); + blocks.blockQuartzGlass = addFeature( BlockQuartzGlass.class ); + blocks.blockQuartzVibrantGlass = addFeature( BlockQuartzLamp.class ); + blocks.blockQuartzPiller = addFeature( BlockQuartzPillar.class ); + blocks.blockQuartzChiseled = addFeature( BlockQuartzChiseled.class ); + blocks.blockQuartzTorch = addFeature( BlockQuartzTorch.class ); + blocks.blockCharger = addFeature( BlockCharger.class ); + + blocks.blockGrindStone = addFeature( BlockGrinder.class ); + blocks.blockCrankHandle = addFeature( BlockCrank.class ); + blocks.blockInscriber = addFeature( BlockInscriber.class ); + blocks.blockWireless = addFeature( BlockWireless.class ); + blocks.blockTinyTNT = addFeature( BlockTinyTNT.class ); + + blocks.blockQuartzCrystalizer = addFeature( BlockQuartzCrystalizer.class ); + blocks.blockNetworkEmitter = addFeature( BlockNetworkEmitter.class ); + + blocks.blockPatternProvider = addFeature( BlockPatternProvider.class ); + blocks.blockAssemblerFieldWall = addFeature( BlockContainmentWall.class ); + blocks.blockHeatVent = addFeature( BlockHeatVent.class ); + blocks.blockCraftingCPU = addFeature( BlockCraftingAccelerator.class ); + + blocks.blockQuantumRing = addFeature( BlockQuantumRing.class ); + blocks.blockQuantumLink = addFeature( BlockQuantumLinkChamber.class ); + + blocks.blockSpatialPylon = addFeature( BlockSpatialPylon.class ); + blocks.blockSpatialIOPort = addFeature( BlockSpatialIOPort.class ); + + blocks.blockController = addFeature( BlockController.class ); + blocks.blockDrive = addFeature( BlockDrive.class ); + blocks.blockChest = addFeature( BlockChest.class ); + blocks.blockInterface = addFeature( BlockInterface.class ); + blocks.blockPartitioner = addFeature( BlockPartitionEditor.class ); + blocks.blockIOPort = addFeature( BlockIOPort.class ); + blocks.blockCondenser = addFeature( BlockCondenser.class ); + blocks.blockEnergyAcceptor = addFeature( BlockEnergyAcceptor.class ); + blocks.blockVibrationChamber = addFeature( BlockVibrationChamber.class ); + + blocks.blockEnergyCell = addFeature( BlockEnergyCell.class ); + blocks.blockEnergyCellDense = addFeature( BlockDenseEnergyCell.class ); + blocks.blockEnergyCellCreative = addFeature( BlockCreativeEnergyCell.class ); + + items.itemEncodedAsemblerPattern = addFeature( ItemEncodedPattern.class ); + + items.itemCellCreative = addFeature( ItemCreativeStorageCell.class ); + + items.itemCell1k = addFeature( ItemBasicStorageCell.class, MaterialType.Cell1kPart, 1 ); + items.itemCell4k = addFeature( ItemBasicStorageCell.class, MaterialType.Cell4kPart, 4 ); + items.itemCell16k = addFeature( ItemBasicStorageCell.class, MaterialType.Cell16kPart, 16 ); + items.itemCell64k = addFeature( ItemBasicStorageCell.class, MaterialType.Cell64kPart, 64 ); + + items.itemSpatialCell2 = addFeature( ItemSpatialStorageCell.class, MaterialType.Cell2SpatialPart, 2 ); + items.itemSpatialCell16 = addFeature( ItemSpatialStorageCell.class, MaterialType.Cell16SpatialPart, 16 ); + items.itemSpatialCell128 = addFeature( ItemSpatialStorageCell.class, MaterialType.Cell128SpatialPart, 128 ); + + items.itemCertusQuartzKnife = addFeature( ToolQuartzCuttingKnife.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzWrench = addFeature( ToolQuartzWrench.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzAxe = addFeature( ToolQuartzAxe.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzHoe = addFeature( ToolQuartzHoe.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzPick = addFeature( ToolQuartzPickaxe.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzShovel = addFeature( ToolQuartzSpade.class, AEFeature.CertusQuartzTools ); + items.itemCertusQuartzSword = addFeature( ToolQuartzSword.class, AEFeature.CertusQuartzTools ); + + items.itemNetherQuartzKnife = addFeature( ToolQuartzCuttingKnife.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzWrench = addFeature( ToolQuartzWrench.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzAxe = addFeature( ToolQuartzAxe.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzHoe = addFeature( ToolQuartzHoe.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzPick = addFeature( ToolQuartzPickaxe.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzShovel = addFeature( ToolQuartzSpade.class, AEFeature.NetherQuartzTools ); + items.itemNetherQuartzSword = addFeature( ToolQuartzSword.class, AEFeature.NetherQuartzTools ); + + items.itemMassCannon = addFeature( ToolMassCannon.class ); + items.itemMemoryCard = addFeature( ToolMemoryCard.class ); + items.itemChargedStaff = addFeature( ToolChargedStaff.class ); + items.itemEntropyManipulator = addFeature( ToolEntropyManipulator.class ); + items.itemWirelessTerminal = addFeature( ToolWirelessTerminal.class ); + + items.itemFacade = addFeature( ItemFacade.class ); + + addFeature( ToolDebugCard.class ); + } + + private AEItemDefinition addFeature(Class c, Object... Args) + { + + try + { + java.lang.reflect.Constructor[] con = c.getConstructors(); + Object obj = null; + + for (Constructor conItem : con) + { + if ( conItem.getParameterTypes().length == Args.length ) + obj = conItem.newInstance( Args ); + } + + if ( obj instanceof IAEFeature ) + { + IAEFeature feature = (IAEFeature) obj; + + for (AEFeature f : feature.feature().getFeatures()) + featuresToEntities.put( f, c ); + + feature.feature().register(); + + return feature.feature(); + } + else if ( obj == null ) + throw new RuntimeException( "No valid constructor found." ); + else + throw new RuntimeException( "Non AE Feature Registered" ); + + } + catch (Throwable e) + { + AELog.severe( "Error with Feature: " + c.getName() ); + throw new RuntimeException( e ); + } + } + + public void Init(FMLInitializationEvent event) + { + AEApi.instance().partHelper().registerNewLayer( "appeng.api.parts.layers.LayerIEnergySink", IEnergySink.class ); + AEApi.instance().partHelper().registerNewLayer( "appeng.api.parts.layers.LayerISidedInventory", ISidedInventory.class ); + AEApi.instance().partHelper().registerNewLayer( "appeng.api.parts.layers.LayerIPowerEmitter", IPowerEmitter.class ); + AEApi.instance().partHelper().registerNewLayer( "appeng.api.parts.layers.LayerIPowerReceptor", IPowerReceptor.class ); + AEApi.instance().partHelper().registerNewLayer( "appeng.api.parts.layers.LayerIFluidHandler", IFluidHandler.class ); + + TickRegistry.registerTickHandler( TickHandler.instance, Side.SERVER ); + TickRegistry.registerTickHandler( TickHandler.instance, Side.CLIENT ); + + MinecraftForge.EVENT_BUS.register( TickHandler.instance ); + MinecraftForge.EVENT_BUS.register( new PartPlacement() ); + + AEApi.instance().registries().gridCache().registerGridCache( ITickManager.class, TickManagerCache.class ); + AEApi.instance().registries().gridCache().registerGridCache( IEnergyGrid.class, EnergyGridCache.class ); + AEApi.instance().registries().gridCache().registerGridCache( IPathingGrid.class, PathGridCache.class ); + AEApi.instance().registries().gridCache().registerGridCache( IStorageGrid.class, GridStorageCache.class ); + AEApi.instance().registries().gridCache().registerGridCache( P2PCache.class, P2PCache.class ); + AEApi.instance().registries().gridCache().registerGridCache( ISpatialCache.class, SpatialPylonCache.class ); + + AEApi.instance().registries().externalStorage().addExternalStorageInterface( new AEExternalHandler() ); + + AEApi.instance().registries().cell().addCellHandler( new BasicCellHandler() ); + AEApi.instance().registries().cell().addCellHandler( new CreativeCellHandler() ); + + NetworkRegistry.instance().registerGuiHandler( AppEng.instance, GuiBridge.GUI_Handler ); + + } + + public void PostInit(FMLPostInitializationEvent event) + { + // add to localizaiton.. + PlayerMessages.values(); + GuiText.values(); + + Api.instance.partHelper.initFMPSupport(); + ((BlockCableBus) AEApi.instance().blocks().blockMultiPart.block()).setupTile(); + + if ( Configuration.instance.isFeatureEnabled( AEFeature.ChestLoot ) ) + { + ChestGenHooks d = ChestGenHooks.getInfo( ChestGenHooks.MINESHAFT_CORRIDOR ); + d.addItem( new WeightedRandomChestContent( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), 1, 4, 2 ) ); + d.addItem( new WeightedRandomChestContent( AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ), 1, 4, 2 ) ); + } + + // add villager trading to black smiths for a few basic materials + if ( Configuration.instance.isFeatureEnabled( AEFeature.VillagerTrading ) ) + VillagerRegistry.instance().registerVillageTradeHandler( 3, new AETrading() ); + + if ( Configuration.instance.isFeatureEnabled( AEFeature.CertusQuartzWorldGen ) ) + GameRegistry.registerWorldGenerator( new QuartzWorldGen() ); + + } +} diff --git a/core/WorldSettings.java b/core/WorldSettings.java new file mode 100644 index 00000000..a1607cf2 --- /dev/null +++ b/core/WorldSettings.java @@ -0,0 +1,144 @@ +package appeng.core; + +import java.io.File; +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +import net.minecraftforge.common.Configuration; +import net.minecraftforge.common.DimensionManager; +import appeng.api.util.WorldCoord; +import appeng.me.GridStorage; +import appeng.me.GridStorageSearch; +import cpw.mods.fml.common.network.Player; + +public class WorldSettings extends Configuration +{ + + private static WorldSettings instance; + + long lastGridStorage = 0; + + public WorldSettings(File f) { + super( f ); + try + { + lastGridStorage = Long.parseLong( get( "Counters", "lastGridStorage", 0 ).getString() ); + } + catch (NumberFormatException err) + { + lastGridStorage = 0; + } + } + + public static WorldSettings getInstance() + { + if ( instance == null ) + { + File f = DimensionManager.getWorld( 0 ).getSaveHandler().getMapFileFromName( "AppEng" ); + instance = new WorldSettings( f ); + } + + return instance; + } + + public void sendToPlayer(Player player) + { + + } + + public void init() + { + save(); + } + + public void shutdown() + { + save(); + instance = null; + } + + private WeakHashMap> loadedStorage = new WeakHashMap(); + + public WorldCoord getStoredSize(int dim) + { + int x = get( "StorageCell" + dim, "scaleX", 0 ).getInt(); + int y = get( "StorageCell" + dim, "scaleY", 0 ).getInt(); + int z = get( "StorageCell" + dim, "scaleZ", 0 ).getInt(); + return new WorldCoord( x, y, z ); + } + + public void setStoredSize(int dim, int targetX, int targetY, int targetZ) + { + get( "StorageCell" + dim, "scaleX", 0 ).set( targetX ); + get( "StorageCell" + dim, "scaleY", 0 ).set( targetY ); + get( "StorageCell" + dim, "scaleZ", 0 ).set( targetZ ); + save(); + } + + /** + * lazy loading, can load any id, even ones that don't exist anymore. + * + * @param storageID + * @return + */ + public GridStorage getGridStorage(long storageID) + { + GridStorageSearch gss = new GridStorageSearch( storageID ); + WeakReference result = loadedStorage.get( gss ); + + if ( result == null || result.get() == null ) + { + String Data = get( "gridstorage", "" + storageID, "" ).getString(); + GridStorage thisStorage = new GridStorage( Data, storageID, gss ); + gss.gridStorage = new WeakReference( thisStorage ); + loadedStorage.put( gss, new WeakReference( gss ) ); + return thisStorage; + } + return result.get().gridStorage.get(); + } + + /** + * create a new storage + */ + public GridStorage getNewGridStorage() + { + long storageID = nextGridStorage(); + GridStorageSearch gss = new GridStorageSearch( storageID ); + GridStorage newStorage = new GridStorage( storageID, gss ); + gss.gridStorage = new WeakReference( newStorage ); + loadedStorage.put( gss, new WeakReference( gss ) ); + return newStorage; + } + + public void destroyGridStorage(long id) + { + this.getCategory( "gridstorage" ).remove( "" + id ); + } + + @Override + public void save() + { + // populate new data + for (GridStorageSearch gs : loadedStorage.keySet()) + { + GridStorage thisStorage = gs.gridStorage.get(); + if ( thisStorage != null && thisStorage.getGrid() != null && !thisStorage.getGrid().isEmpty() ) + { + String value = thisStorage.getValue(); + get( "gridstorage", "" + thisStorage.getID(), value ).set( value ); + } + } + + // save to files + if ( hasChanged() ) + super.save(); + } + + private long nextGridStorage() + { + long r = lastGridStorage++; + get( "Counters", "lastGridStorage", lastGridStorage ).set( Long.toString( lastGridStorage ) ); + return r; + } + +} diff --git a/core/api/ApiPart.java b/core/api/ApiPart.java new file mode 100644 index 00000000..27895141 --- /dev/null +++ b/core/api/ApiPart.java @@ -0,0 +1,344 @@ +package appeng.core.api; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.client.MinecraftForgeClient; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.commons.Remapper; +import org.objectweb.asm.commons.RemappingClassAdapter; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import appeng.api.parts.IPartItem; +import appeng.api.parts.IPartHelper; +import appeng.api.parts.LayerBase; +import appeng.client.render.BusRenderer; +import appeng.core.AELog; +import appeng.core.AppEng; +import appeng.helpers.PartPlacement; +import appeng.integration.abstraction.IFMP; +import appeng.tile.networking.TileCableBus; +import appeng.util.Platform; + +import com.google.common.base.Joiner; + +public class ApiPart implements IPartHelper +{ + + int classNum = 1; + + HashMap TileImplementations = new HashMap(); + HashMap readerCache = new HashMap(); + HashMap interfaces2Layer = new HashMap(); + HashMap roots = new HashMap(); + + List desc = new LinkedList(); + + public void initFMPSupport() + { + for (Class layerInterface : interfaces2Layer.keySet()) + { + if ( AppEng.instance.isIntegrationEnabled( "FMP" ) ) + ((IFMP) AppEng.instance.getIntegration( "FMP" )).registerPassThru( layerInterface ); + } + } + + private Class loadClass(String Name, byte[] b) + { + // override classDefine (as it is protected) and define the class. + Class clazz = null; + try + { + ClassLoader loader = getClass().getClassLoader();// ClassLoader.getSystemClassLoader(); + Class root = ClassLoader.class; + Class cls = loader.getClass(); + java.lang.reflect.Method defineClassMethod = root.getDeclaredMethod( "defineClass", + new Class[] { String.class, byte[].class, int.class, int.class } ); + java.lang.reflect.Method runTransformersMethod = cls + .getDeclaredMethod( "runTransformers", new Class[] { String.class, String.class, byte[].class } ); + + runTransformersMethod.setAccessible( true ); + defineClassMethod.setAccessible( true ); + try + { + Object[] argsA = new Object[] { Name, Name, b }; + b = (byte[]) runTransformersMethod.invoke( loader, argsA ); + + Object[] args = new Object[] { Name, b, new Integer( 0 ), new Integer( b.length ) }; + clazz = (Class) defineClassMethod.invoke( loader, args ); + } + finally + { + runTransformersMethod.setAccessible( false ); + defineClassMethod.setAccessible( false ); + } + } + catch (Exception e) + { + e.printStackTrace(); + System.exit( 1 ); + } + return clazz; + } + + public ClassNode getReader(String name) + { + // if ( readerCache.get( name ) != null ) + // return readerCache.get( name ); + + ClassReader cr; + try + { + String path = "/" + name.replace( ".", "/" ) + ".class"; + InputStream is = getClass().getResourceAsStream( path ); + cr = new ClassReader( is ); + ClassNode cn = new ClassNode(); + cr.accept( cn, ClassReader.EXPAND_FRAMES ); + // readerCache.put( name, cn ); + return cn; + } + catch (Throwable e) + { + e.printStackTrace(); + } + + return null; + } + + public Class getCombinedInstance(String base)// , CableBusContainer cbc) + { + /* + * List desc = new LinkedList(); for (ForgeDirection side : ForgeDirection.values()) { IBusPart part = + * cbc.getPart( side ); if ( part != null ) { for (Class c : interfaces2Layer.keySet()) { if ( c.isInstance( + * part ) ) desc.add( interfaces2Layer.get( c ).getName() ); } } } + */ + + if ( desc.size() == 0 ) + { + try + { + return Class.forName( base ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + String description = base + ":" + Joiner.on( ";" ).skipNulls().join( desc.iterator() ); + + if ( TileImplementations.get( description ) != null ) + { + try + { + return TileImplementations.get( description ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + String f = base;// TileCableBus.class.getName(); + String Addendum = ""; + try + { + Addendum = Class.forName( base ).getSimpleName(); + } + catch (ClassNotFoundException e) + { + e.printStackTrace(); + } + Class myCLass; + + try + { + myCLass = Class.forName( f ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + + String path = f; + + for (String name : desc) + { + path = path + ";" + name; + try + { + myCLass = getClassByDesc( Addendum, path, f, interfaces2Layer.get( Class.forName( name ) ) ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + f = myCLass.getName(); + } + + TileImplementations.put( description, myCLass ); + + try + { + return myCLass; + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + class DefaultPackageClassNameRemapper extends Remapper + { + + public HashMap inputOutput = new HashMap(); + + @Override + public String map(String typeName) + { + String o = inputOutput.get( typeName ); + if ( o == null ) + return typeName; + return o; + } + + } + + public Class getClassByDesc(String Addendum, String fullPath, String root, String next) + { + if ( roots.get( fullPath ) != null ) + return roots.get( fullPath ); + + ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS ); + ClassNode n = getReader( next ); + String originalName = n.name; + try + { + n.name = n.name + "_" + Addendum; + n.superName = Class.forName( root ).getName().replace( ".", "/" ); + } + catch (Throwable t) + { + t.printStackTrace(); + } + + for (MethodNode mn : n.methods) + { + Iterator i = mn.instructions.iterator(); + while (i.hasNext()) + { + processNode( i.next(), n.superName ); + } + } + + DefaultPackageClassNameRemapper remapper = new DefaultPackageClassNameRemapper(); + remapper.inputOutput.put( "appeng/api/parts/LayerBase", n.superName ); + remapper.inputOutput.put( originalName, n.name ); + n.accept( new RemappingClassAdapter( cw, remapper ) ); + // n.accept( cw ); + + // n.accept( new TraceClassVisitor( new PrintWriter( System.out ) ) ); + byte[] barray = cw.toByteArray(); + int size = barray.length; + Class nclass = loadClass( n.name.replace( "/", "." ), barray ); + + try + { + Object fish = nclass.newInstance(); + Class rootC = Class.forName( root ); + + boolean bads = false; + + if ( !rootC.isInstance( fish ) ) + { + bads = true; + AELog.severe( "Error, Expected layer to implement " + root + " did not." ); + } + + if ( fish instanceof LayerBase ) + { + bads = true; + AELog.severe( "Error, Expected layer to NOT implement LayerBase but it DID." ); + } + + if ( !(fish instanceof TileCableBus) ) + { + bads = true; + AELog.severe( "Error, Expected layer to implement TileCableBus did not." ); + } + + if ( !(fish instanceof TileEntity) ) + { + bads = true; + AELog.severe( "Error, Expected layer to implement TileEntity did not." ); + } + + if ( !bads ) + { + AELog.info( "Layer: " + n.name + " loaded successfully - " + size + " bytes" ); + } + + } + catch (Throwable t) + { + AELog.severe( "Layer: " + n.name + " Failed." ); + t.printStackTrace(); + } + + roots.put( fullPath, nclass ); + return nclass; + } + + private void processNode(AbstractInsnNode next, String nePar) + { + if ( next instanceof MethodInsnNode ) + { + MethodInsnNode min = (MethodInsnNode) next; + if ( min.owner.equals( "appeng/api/parts/LayerBase" ) ) + { + min.owner = nePar; + } + } + } + + @Override + public void setItemBusRenderer(IPartItem i) + { + if ( Platform.isClient() && i instanceof Item ) + MinecraftForgeClient.registerItemRenderer( ((Item) i).itemID, BusRenderer.instance ); + } + + @Override + public boolean placeBus(ItemStack is, int x, int y, int z, int side, EntityPlayer player, World w) + { + return PartPlacement.place( is, x, y, z, side, player, w, PartPlacement.PlaceType.PLACE_ITEM, 0 ); + } + + @Override + public boolean registerNewLayer(String layer, Class layerInterface) + { + if ( interfaces2Layer.get( layerInterface ) == null ) + { + desc.add( layerInterface.getName() ); + interfaces2Layer.put( layerInterface, layer ); + } + else + AELog.info( "Layer " + layer + " not registered, " + layerInterface.getName() + " aready has a layer." ); + + return false; + } + +} diff --git a/core/api/ApiStorage.java b/core/api/ApiStorage.java new file mode 100644 index 00000000..64831897 --- /dev/null +++ b/core/api/ApiStorage.java @@ -0,0 +1,34 @@ +package appeng.core.api; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import appeng.api.storage.IStorageHelper; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.util.item.AEFluidStack; +import appeng.util.item.AEItemStack; +import appeng.util.item.ItemList; + +public class ApiStorage implements IStorageHelper +{ + + @Override + public IAEItemStack createItemStack(ItemStack is) + { + return AEItemStack.create( is ); + } + + @Override + public IAEFluidStack createFluidStack(FluidStack is) + { + return AEFluidStack.create( is ); + } + + @Override + public IItemList createItemList() + { + return new ItemList(); + } + +} diff --git a/core/crash/CrashEnhancement.java b/core/crash/CrashEnhancement.java new file mode 100644 index 00000000..e8ae27ca --- /dev/null +++ b/core/crash/CrashEnhancement.java @@ -0,0 +1,50 @@ +package appeng.core.crash; + +import appeng.core.Configuration; +import appeng.integration.IntegrationRegistry; +import cpw.mods.fml.common.ICrashCallable; + +public class CrashEnhancement implements ICrashCallable +{ + + final CrashInfo Output; + + public CrashEnhancement(CrashInfo ci) { + Output = ci; + } + + @Override + public String call() throws Exception + { + switch (Output) + { + case MOD_VERSION: + return Configuration.CHANNEL + " " + Configuration.VERSION + " for Forge " + + net.minecraftforge.common.ForgeVersion.majorVersion + "." // majorVersion + + net.minecraftforge.common.ForgeVersion.minorVersion + "." // minorVersion + + net.minecraftforge.common.ForgeVersion.revisionVersion + "." // revisionVersion + + net.minecraftforge.common.ForgeVersion.buildVersion; + case INTEGRATION: + if ( IntegrationRegistry.instance == null ) + return "N/A"; + return IntegrationRegistry.instance.getStatus(); + } + + return "UNKNOWN_VALUE"; + } + + @Override + public String getLabel() + { + switch (Output) + { + case MOD_VERSION: + return "AE2 Version"; + case INTEGRATION: + return "AE2 Integration"; + } + + return "AE2_UNKNOWN"; + } + +} diff --git a/core/crash/CrashInfo.java b/core/crash/CrashInfo.java new file mode 100644 index 00000000..8aab2115 --- /dev/null +++ b/core/crash/CrashInfo.java @@ -0,0 +1,6 @@ +package appeng.core.crash; + +public enum CrashInfo +{ + MOD_VERSION, INTEGRATION +} diff --git a/core/features/AEFeature.java b/core/features/AEFeature.java new file mode 100644 index 00000000..1d4f0dff --- /dev/null +++ b/core/features/AEFeature.java @@ -0,0 +1,75 @@ +package appeng.core.features; + +public enum AEFeature +{ + Core(null), // stuff that has no reason for ever being turned off, or that + // is just flat out required by tons of + // important stuff. + + CertusQuartzWorldGen("World"), + + DecorativeLights("DecorativeLights"), DecorativeQuartzBlocks("World"), + + GrindStone("World"), Flour("World"), Inscriber("World"), + + ChestLoot("World"), VillagerTrading("World"), + + TinyTNT("World"), + + PoweredTools("ToolsClassifications"), + + CertusQuartzTools("ToolsClassifications"), + + NetherQuartzTools("ToolsClassifications"), + + QuartzHoe("Tools"), QuartzSpade("Tools"), QuartzSword("Tools"), QuartzPickaxe("Tools"), QuartzAxe("Tools"), QuartzKnife("Tools"), QuartzWrench("Tools"), + + ChargedStaff("Tools"), EntropyManipulator("Tools"), MatterCannon("Tools"), WirelessAccessTerminal("Tools"), + + PowerGen("NetworkFeatures"), + + Crafting("NetworkFeatures"), MolecularAssembler("NetworkFeatures"), SpatialIO("NetworkFeatures"), QuantumNetworkBridge("NetworkFeatures"), + + LevelEmiter("NetworkBuses"), CraftingTerminal("NetworkBuses"), StorageMonitor("NetworkBuses"), P2PTunnel("NetworkBuses"), FormationPlane("NetworkBuses"), AnnihilationPlane( + "NetworkBuses"), ImportBus("NetworkBuses"), ExportBus("NetworkBuses"), StorageBus("NetworkBuses"), PartConversionMonitor("NetworkBuses"), + + StorageCells("Storage"), MEChest("Storage"), MEDrive("Storage"), IOPort("Storage"), + + DenseEnergyCells("HigherCapacity"), DenseCables("HigherCapacity"), + + P2PTunnelME("P2PTunnels"), P2PTunnelItems("P2PTunnels"), P2PTunnelRedstone("P2PTunnels"), P2PTunnelEU("P2PTunnels"), P2PTunnelMJ("P2PTunnels"), P2PTunnelLiquids("P2PTunnels"), + + MassCannonBlockDamage("BlockFeatures"), TinyTNTBlockDamage("BlockFeatures"), Facades("Facades"), + + DuplicateItems("Misc", false), Profiler("Services"), VersionChecker("Services"), Debug("Misc"), Creative("Misc"); + + String Category; + boolean visible = true; + boolean defValue = true; + + private AEFeature(String cat) { + Category = cat; + visible = !this.name().equals( "Core" ); + } + + private AEFeature(String cat, boolean defv) { + this( cat ); + defValue = defv; + } + + public String getCategory() + { + return Category; + } + + public Boolean defaultVaue() + { + return defValue; + } + + public Boolean isVisible() + { + return visible; + } + +} diff --git a/core/features/AEFeatureHandler.java b/core/features/AEFeatureHandler.java new file mode 100644 index 00000000..1cfdc1c8 --- /dev/null +++ b/core/features/AEFeatureHandler.java @@ -0,0 +1,164 @@ +package appeng.core.features; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import appeng.api.util.AEItemDefinition; +import appeng.block.AEBaseBlock; +import appeng.block.AEBaseItemBlock; +import appeng.core.AELog; +import appeng.core.CommonHelper; +import appeng.core.Configuration; +import appeng.core.CreativeTab; +import appeng.util.Platform; +import cpw.mods.fml.common.registry.GameRegistry; + +public class AEFeatureHandler implements AEItemDefinition +{ + + private final EnumSet myFeatures; + + private final String subname; + private IAEFeature obj; + + private Item ItemData; + private Block BlockData; + private ItemStack StackData; + + public AEFeatureHandler(EnumSet featureSet, IAEFeature _obj, String _subname) { + myFeatures = featureSet; + obj = _obj; + subname = _subname; + } + + public void register() + { + if ( isFeatureAvailable() ) + { + if ( obj instanceof Item ) + initItem( (Item) obj ); + if ( obj instanceof Block ) + initBlock( (Block) obj ); + } + } + + public static String getName(Class o, String subname) + { + String name = o.getSimpleName(); + + if ( subname != null ) + { + // simple hack to allow me to do get nice names for these without + // mode code outside of AEBaseItem + if ( subname.equals( "CertusQuartzTools" ) ) + return name.replace( "Quartz", "CertusQuartz" ); + if ( subname.equals( "NetherQuartzTools" ) ) + return name.replace( "Quartz", "NetherQuartz" ); + + name += "." + subname; + } + + return name; + } + + private void initItem(Item i) + { + ItemData = i; + StackData = new ItemStack( i ); + + String name = getName( i.getClass(), subname ); + i.setTextureName( "appliedenergistics2:" + name ); + i.setCreativeTab( CreativeTab.instance ); + i.setUnlocalizedName( /* "item." */"appliedenergistics2." + name ); + + GameRegistry.registerItem( i, "item." + name ); + AELog.localization( "item", i.getUnlocalizedName() ); + } + + private void initBlock(Block b) + { + BlockData = b; + StackData = new ItemStack( b ); + + String name = getName( b.getClass(), subname ); + b.setCreativeTab( CreativeTab.instance ); + b.setUnlocalizedName( /* "tile." */"appliedenergistics2." + name ); + b.setTextureName( "appliedenergistics2:" + name ); + + if ( Platform.isClient() && BlockData instanceof AEBaseBlock ) + { + AEBaseBlock bb = (AEBaseBlock) b; + CommonHelper.proxy.bindTileEntitySpecialRenderer( bb.getTileEntityClass(), bb ); + } + + Class itemBlock = AEBaseItemBlock.class; + if ( b instanceof AEBaseBlock ) + itemBlock = ((AEBaseBlock) b).getItemBlockClass(); + + GameRegistry.registerBlock( b, itemBlock, "tile." + name ); + AELog.localization( "block", b.getUnlocalizedName() ); + } + + public EnumSet getFeatures() + { + return myFeatures.clone(); + } + + public boolean isFeatureAvailable() + { + boolean enabled = true; + + for (AEFeature f : myFeatures) + enabled = enabled && Configuration.instance.isFeatureEnabled( f ); + + return enabled; + } + + @Override + public Block block() + { + return BlockData; + } + + @Override + public Class entity() + { + if ( BlockData instanceof AEBaseBlock ) + { + AEBaseBlock bb = (AEBaseBlock) BlockData; + return bb.getTileEntityClass(); + } + + return null; + } + + @Override + public Item item() + { + return ItemData; + } + + @Override + public ItemStack stack(int stackSize) + { + if ( isFeatureAvailable() ) + { + ItemStack rv = StackData.copy(); + rv.stackSize = stackSize; + return rv; + } + return null; + } + + @Override + public boolean sameAs(ItemStack is) + { + if ( isFeatureAvailable() ) + return Platform.isSameItemType( is, StackData ); + return false; + } + +} diff --git a/core/features/IAEFeature.java b/core/features/IAEFeature.java new file mode 100644 index 00000000..ea6b703b --- /dev/null +++ b/core/features/IAEFeature.java @@ -0,0 +1,8 @@ +package appeng.core.features; + +public interface IAEFeature +{ + + public AEFeatureHandler feature(); + +} diff --git a/core/features/registries/CellRegistry.java b/core/features/registries/CellRegistry.java new file mode 100644 index 00000000..dd33a13d --- /dev/null +++ b/core/features/registries/CellRegistry.java @@ -0,0 +1,68 @@ +package appeng.core.features.registries; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.item.ItemStack; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.ICellRegistry; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; + +public class CellRegistry implements ICellRegistry +{ + + List handlers; + + public CellRegistry() { + handlers = new ArrayList(); + } + + @Override + public void addCellHandler(ICellHandler h) + { + if ( h != null ) + handlers.add( h ); + } + + @Override + public boolean isCellHandled(ItemStack is) + { + if ( is == null ) + return false; + for (ICellHandler ch : handlers) + if ( ch.isCell( is ) ) + return true; + return false; + } + + @Override + public ICellHandler getHander(ItemStack is) + { + if ( is == null ) + return null; + for (ICellHandler ch : handlers) + { + if ( ch.isCell( is ) ) + { + return ch; + } + } + return null; + } + + @Override + public IMEInventoryHandler getCellInventory(ItemStack is, StorageChannel chan) + { + if ( is == null ) + return null; + for (ICellHandler ch : handlers) + { + if ( ch.isCell( is ) ) + { + return ch.getCellInventory( is, chan ); + } + } + return null; + } +} diff --git a/core/features/registries/ExternalStorageRegistry.java b/core/features/registries/ExternalStorageRegistry.java new file mode 100644 index 00000000..6a6d75ab --- /dev/null +++ b/core/features/registries/ExternalStorageRegistry.java @@ -0,0 +1,38 @@ +package appeng.core.features.registries; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IExternalStorageRegistry; +import appeng.api.storage.StorageChannel; + +public class ExternalStorageRegistry implements IExternalStorageRegistry +{ + + List Handlers; + + public ExternalStorageRegistry() { + Handlers = new ArrayList(); + } + + @Override + public IExternalStorageHandler getHandler(TileEntity te, ForgeDirection d, StorageChannel chan) + { + for (IExternalStorageHandler x : Handlers) + { + if ( x.canHandle( te, d, chan ) ) + return x; + } + return null; + } + + @Override + public void addExternalStorageInterface(IExternalStorageHandler ei) + { + Handlers.add( ei ); + } + +} diff --git a/core/features/registries/GridCacheRegistry.java b/core/features/registries/GridCacheRegistry.java new file mode 100644 index 00000000..0f7920d2 --- /dev/null +++ b/core/features/registries/GridCacheRegistry.java @@ -0,0 +1,46 @@ +package appeng.core.features.registries; + +import java.lang.reflect.Constructor; +import java.util.HashMap; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridCacheRegistry; +import appeng.core.AELog; + +public class GridCacheRegistry implements IGridCacheRegistry +{ + + final private HashMap, Class> caches = new HashMap(); + + @Override + public void registerGridCache(Class iface, Class implementation) + { + if ( iface.isAssignableFrom( implementation ) ) + caches.put( iface, implementation ); + else + throw new RuntimeException( "Invalid setup, grid cache must either be the same class, or an interface that the implementation implements" ); + } + + @Override + public HashMap, IGridCache> createCacheInstance(IGrid g) + { + HashMap, IGridCache> map = new HashMap(); + + for (Class iface : caches.keySet()) + { + try + { + Constructor c = caches.get( iface ).getConstructor( IGrid.class ); + map.put( iface, c.newInstance( g ) ); + } + catch (Throwable e) + { + AELog.severe( "Grid Caches must have a constructor with IGrid as the single param." ); + throw new RuntimeException( e ); + } + } + + return map; + } +} diff --git a/core/features/registries/GrinderRecipeManager.java b/core/features/registries/GrinderRecipeManager.java new file mode 100644 index 00000000..45ab968a --- /dev/null +++ b/core/features/registries/GrinderRecipeManager.java @@ -0,0 +1,227 @@ +package appeng.core.features.registries; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.api.features.IGrinderEntry; +import appeng.api.features.IGrinderRegistry; +import appeng.core.AELog; +import appeng.core.Configuration; +import appeng.core.features.registries.entries.AppEngGrinderRecipe; +import appeng.recipes.ores.IOreListener; +import appeng.recipes.ores.OreDictionaryHandler; +import appeng.util.Platform; + +public class GrinderRecipeManager implements IGrinderRegistry, IOreListener +{ + + public List RecipeList; + + private ItemStack copy(ItemStack is) + { + if ( is != null ) + return is.copy(); + return null; + } + + public GrinderRecipeManager() { + RecipeList = new ArrayList(); + + addOre( "Gold", new ItemStack( Block.oreGold ) ); + addOre( "Iron", new ItemStack( Block.oreIron ) ); + addIngot( "Gold", new ItemStack( Item.ingotGold ) ); + addIngot( "Iron", new ItemStack( Item.ingotIron ) ); + addOre( "Obsidian", new ItemStack( Block.obsidian ) ); + addOre( "EnderPearl", new ItemStack( Item.enderPearl ) ); + addOre( "Coal", new ItemStack( Item.coal ) ); + addOre( "Charcoal", new ItemStack( Item.coal, 1, 1 ) ); + + OreDictionaryHandler.instance.observe( this ); + } + + @Override + public List getRecipes() + { + log( "API - getRecipes" ); + return RecipeList; + } + + @Override + public void addRecipe(ItemStack in, ItemStack out, int cost) + { + if ( in == null || out == null ) + { + log( "Invalid Grinder Recipe Specified." ); + return; + } + + log( "Allow Grinding of " + Platform.getItemDisplayName( in ) + " to " + Platform.getItemDisplayName( out ) + " for " + + cost ); + RecipeList.add( new AppEngGrinderRecipe( copy( in ), copy( out ), cost ) ); + } + + @Override + public void addRecipe(ItemStack in, ItemStack out, ItemStack optional, float chance, int cost) + { + if ( in == null || (optional == null && out == null) ) + { + log( "Invalid Grinder Recipe Specified." ); + return; + } + + log( "Allow Grinding of " + Platform.getItemDisplayName( in ) + " to " + Platform.getItemDisplayName( out ) + + " with optional " + Platform.getItemDisplayName( optional ) + " for " + cost ); + RecipeList.add( new AppEngGrinderRecipe( copy( in ), copy( out ), copy( optional ), chance, cost ) ); + } + + @Override + public IGrinderEntry getRecipeForInput(ItemStack input) + { + log( "Looking up recipe for " + Platform.getItemDisplayName( input ) ); + if ( input != null ) + { + for (IGrinderEntry r : RecipeList) + { + if ( Platform.isSameItem( input, r.getInput() ) ) + { + log( "Recipe for " + input.getUnlocalizedName() + " found " + Platform.getItemDisplayName( r.getOutput() ) ); + return r; + } + } + + log( "Count not find recipe for " + Platform.getItemDisplayName( input ) ); + } + + return null; + } + + public void log(String o) + { + AELog.grinder( o ); + } + + private int getDustToOreRatio(String name) + { + if ( name.equals( "Obsidian" ) ) + return 1; + if ( name.equals( "EnderPearl" ) ) + return 1; + if ( name.equals( "Charcoal" ) ) + return 1; + if ( name.equals( "Coal" ) ) + return 1; + if ( name.contains( "Quartz" ) ) + return 1; + return 2; + } + + public Map Ores = new HashMap(); + public Map Ingots = new HashMap(); + public Map Dusts = new HashMap(); + + private void addOre(String name, ItemStack item) + { + if ( item == null ) + return; + log( "Adding Ore - " + name + " : " + Platform.getItemDisplayName( item ) ); + + Ores.put( item, name ); + + if ( Dusts.containsKey( name ) ) + { + ItemStack is = Dusts.get( name ).copy(); + int ratio = getDustToOreRatio( name ); + if ( ratio > 1 ) + { + ItemStack extra = is.copy(); + extra.stackSize = ratio - 1; + addRecipe( item, is, extra, (float) (Configuration.instance.oreDoublePercentage / 100.0), 8 ); + } + else + addRecipe( item, is, 8 ); + } + } + + private void addIngot(String name, ItemStack item) + { + if ( item == null ) + return; + log( "Adding Ingot - " + name + " : " + Platform.getItemDisplayName( item ) ); + + Ingots.put( item, name ); + + if ( Dusts.containsKey( name ) ) + { + addRecipe( item, Dusts.get( name ), 4 ); + } + } + + private void addDust(String name, ItemStack item) + { + if ( item == null ) + return; + if ( Dusts.containsKey( name ) ) + { + log( "Rejecting Dust - " + name + " : " + Platform.getItemDisplayName( item ) ); + return; + } + + log( "Adding Dust - " + name + " : " + Platform.getItemDisplayName( item ) ); + + Dusts.put( name, item ); + + for (Entry d : Ores.entrySet()) + if ( name.equals( d.getValue() ) ) + { + ItemStack is = item.copy(); + is.stackSize = 1; + int ratio = getDustToOreRatio( name ); + if ( ratio > 1 ) + { + ItemStack extra = is.copy(); + extra.stackSize = ratio - 1; + addRecipe( d.getKey(), is, extra, (float) (Configuration.instance.oreDoublePercentage / 100.0), 8 ); + } + else + addRecipe( d.getKey(), is, 8 ); + } + + for (Entry d : Ingots.entrySet()) + if ( name.equals( d.getValue() ) ) + addRecipe( d.getKey(), item, 4 ); + } + + @Override + public void oreRegistered(String Name, ItemStack item) + { + if ( Name.startsWith( "ore" ) || Name.startsWith( "ingot" ) || Name.startsWith( "dust" ) ) + { + for (String ore : Configuration.instance.grinderOres) + { + if ( ore.equals( "CertusQuartz" ) ) + continue; + if ( ore.equals( "NetherQuartz" ) ) + continue; + + if ( Name.equals( "ore" + ore ) ) + { + addOre( ore, item ); + } + else if ( Name.equals( "ingot" + ore ) ) + { + addIngot( ore, item ); + } + else if ( Name.equals( "dust" + ore ) ) + { + addDust( ore, item ); + } + } + } + } +} diff --git a/core/features/registries/LocateableRegistry.java b/core/features/registries/LocateableRegistry.java new file mode 100644 index 00000000..8ddc473a --- /dev/null +++ b/core/features/registries/LocateableRegistry.java @@ -0,0 +1,45 @@ +package appeng.core.features.registries; + +import java.util.HashMap; + +import net.minecraftforge.event.ForgeSubscribe; +import appeng.api.events.LocatableEventAnnounce; +import appeng.api.events.LocatableEventAnnounce.LocatableEvent; +import appeng.api.features.ILocatable; +import appeng.api.features.ILocateableRegistry; +import appeng.util.Platform; + +public class LocateableRegistry implements ILocateableRegistry +{ + + private HashMap set; + + @ForgeSubscribe + public void updateLocateable(LocatableEventAnnounce e) + { + if ( Platform.isClient() ) + return; // IGNORE! + + if ( e.change == LocatableEvent.Register ) + { + set.put( e.target.getLocatableSerial(), e.target ); + } else if ( e.change == LocatableEvent.Unregister ) + { + set.remove( e.target.getLocatableSerial() ); + } + } + + public LocateableRegistry() { + set = new HashMap(); + } + + /** + * Find a locate-able object by its serial. + */ + @Override + public Object findLocateableBySerial(long ser) + { + return set.get( ser ); + } + +} diff --git a/core/features/registries/MovableTileRegistry.java b/core/features/registries/MovableTileRegistry.java new file mode 100644 index 00000000..7f34b7b3 --- /dev/null +++ b/core/features/registries/MovableTileRegistry.java @@ -0,0 +1,129 @@ +package appeng.core.features.registries; + +import java.util.HashMap; +import java.util.LinkedList; + +import net.minecraft.tileentity.TileEntity; +import appeng.api.exceptions.AppEngException; +import appeng.api.movable.IMovableHandler; +import appeng.api.movable.IMovableRegistry; +import appeng.api.movable.IMovableTile; +import appeng.spatial.DefaultSpatialHandler; + +public class MovableTileRegistry implements IMovableRegistry +{ + + private HashMap, IMovableHandler> Valid = new HashMap, IMovableHandler>(); + private LinkedList> test = new LinkedList>(); + private LinkedList handlers = new LinkedList(); + private DefaultSpatialHandler dsh = new DefaultSpatialHandler(); + + private IMovableHandler nullHandler = new DefaultSpatialHandler(); + + private IMovableHandler testClass(Class myClass, TileEntity te) + { + IMovableHandler handler = null; + + // ask handlers... + for (IMovableHandler han : handlers) + { + if ( han.canHandle( myClass, te ) ) + { + handler = han; + break; + } + } + + // if you have a handler your opted in + if ( handler != null ) + { + Valid.put( myClass, handler ); + return handler; + + } + + // if your movable our opted in + if ( te instanceof IMovableTile ) + { + Valid.put( myClass, dsh ); + return dsh; + } + + // if you are on the white list your opted in. + for (Class testClass : test) + { + if ( testClass.isAssignableFrom( myClass ) ) + { + Valid.put( myClass, dsh ); + return dsh; + } + } + + Valid.put( myClass, nullHandler ); + return nullHandler; + } + + @Override + public boolean askToMove(TileEntity te) + { + Class myClass = te.getClass(); + IMovableHandler canMove = Valid.get( myClass ); + + if ( canMove == null ) + canMove = testClass( myClass, te ); + + if ( canMove != nullHandler ) + { + if ( te instanceof IMovableTile ) + ((IMovableTile) te).prepareToMove(); + + te.invalidate(); + return true; + } + + return false; + } + + @Override + public void doneMoving(TileEntity te) + { + if ( te instanceof IMovableTile ) + { + IMovableTile mt = (IMovableTile) te; + mt.doneMoving(); + } + } + + @Override + public void whiteListTileEntity(Class c) + { + + if ( c.getName().equals( TileEntity.class.getName() ) ) + { + throw new RuntimeException( new AppEngException( "Someone tried to make all tiles movable, this is a clear violation of the purpose of the white list." ) ); + } + + test.add( c ); + } + + @Override + public void addHandler(IMovableHandler han) + { + handlers.add( han ); + } + + @Override + public IMovableHandler getHandler(TileEntity te) + { + Class myClass = te.getClass(); + IMovableHandler h = Valid.get( myClass ); + return h == null ? dsh : h; + } + + @Override + public IMovableHandler getDefaultHandler() + { + return dsh; + } + +} diff --git a/core/features/registries/P2PTunnelRegistry.java b/core/features/registries/P2PTunnelRegistry.java new file mode 100644 index 00000000..b1bab658 --- /dev/null +++ b/core/features/registries/P2PTunnelRegistry.java @@ -0,0 +1,40 @@ +package appeng.core.features.registries; + +import java.util.HashMap; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidContainerRegistry; +import appeng.api.config.TunnelType; +import appeng.api.features.IP2PTunnelRegistry; +import appeng.util.Platform; + +public class P2PTunnelRegistry implements IP2PTunnelRegistry +{ + + HashMap Tunnels = new HashMap(); + + @Override + public void addNewAttunement(ItemStack trigger, TunnelType type) + { + if ( type == null ) + throw new RuntimeException( "Invalid Tunnel Type." ); + + Tunnels.put( trigger, type ); + } + + @Override + public TunnelType getTunnelTypeByItem(ItemStack trigger) + { + if ( FluidContainerRegistry.isContainer( trigger ) ) + return TunnelType.FLUID; + + for (ItemStack is : Tunnels.keySet()) + { + if ( Platform.isSameItemType( is, trigger ) ) + return Tunnels.get( is ); + } + + return null; + } + +} diff --git a/core/features/registries/RegistryContainer.java b/core/features/registries/RegistryContainer.java new file mode 100644 index 00000000..0ec85090 --- /dev/null +++ b/core/features/registries/RegistryContainer.java @@ -0,0 +1,81 @@ +package appeng.core.features.registries; + +import appeng.api.features.IGrinderRegistry; +import appeng.api.features.ILocateableRegistry; +import appeng.api.features.IP2PTunnelRegistry; +import appeng.api.features.IRegistryContainer; +import appeng.api.features.ISpecialComparisonRegistry; +import appeng.api.features.IWirelessTermRegistery; +import appeng.api.movable.IMovableRegistry; +import appeng.api.networking.IGridCacheRegistry; +import appeng.api.storage.ICellRegistry; +import appeng.api.storage.IExternalStorageRegistry; + +public class RegistryContainer implements IRegistryContainer +{ + + private GrinderRecipeManager GrinderRecipes = new GrinderRecipeManager(); + private ExternalStorageRegistry ExternalStorageHandlers = new ExternalStorageRegistry(); + private CellRegistry CellRegistry = new CellRegistry(); + private LocateableRegistry LocateableRegistry = new LocateableRegistry(); + private SpecialComparisonRegistry SpecialComparsonRegistry = new SpecialComparisonRegistry(); + private WirelessRegistry WirelessRegistery = new WirelessRegistry(); + private GridCacheRegistry GridCacheRegistry = new GridCacheRegistry(); + private P2PTunnelRegistry P2PRegistry = new P2PTunnelRegistry(); + private MovableTileRegistry MoveableReg = new MovableTileRegistry(); + + @Override + public IWirelessTermRegistery wireless() + { + return WirelessRegistery; + } + + @Override + public ICellRegistry cell() + { + return CellRegistry; + } + + @Override + public IGrinderRegistry grinder() + { + return GrinderRecipes; + } + + @Override + public ISpecialComparisonRegistry specialComparson() + { + return SpecialComparsonRegistry; + } + + @Override + public IExternalStorageRegistry externalStorage() + { + return ExternalStorageHandlers; + } + + @Override + public ILocateableRegistry locateable() + { + return LocateableRegistry; + } + + @Override + public IGridCacheRegistry gridCache() + { + return GridCacheRegistry; + } + + @Override + public IMovableRegistry moveable() + { + return MoveableReg; + } + + @Override + public IP2PTunnelRegistry p2pTunnel() + { + return P2PRegistry; + } + +} diff --git a/core/features/registries/SpecialComparisonRegistry.java b/core/features/registries/SpecialComparisonRegistry.java new file mode 100644 index 00000000..6bd33935 --- /dev/null +++ b/core/features/registries/SpecialComparisonRegistry.java @@ -0,0 +1,41 @@ +package appeng.core.features.registries; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.item.ItemStack; +import appeng.api.features.IItemComparisionProvider; +import appeng.api.features.IItemComparison; +import appeng.api.features.ISpecialComparisonRegistry; + +public class SpecialComparisonRegistry implements ISpecialComparisonRegistry +{ + + private List CompRegistry; + + public SpecialComparisonRegistry() { + CompRegistry = new ArrayList(); + } + + @Override + public IItemComparison getSpecialComparion(ItemStack stack) + { + for (IItemComparisionProvider i : CompRegistry) + { + IItemComparison comp = i.getComparison( stack ); + if ( comp != null ) + { + return comp; + } + } + + return null; + } + + @Override + public void addComparisonProvider(IItemComparisionProvider prov) + { + CompRegistry.add( prov ); + } + +} diff --git a/core/features/registries/WirelessRangeResult.java b/core/features/registries/WirelessRangeResult.java new file mode 100644 index 00000000..0a2626c9 --- /dev/null +++ b/core/features/registries/WirelessRangeResult.java @@ -0,0 +1,16 @@ +package appeng.core.features.registries; + +import net.minecraft.tileentity.TileEntity; + +public class WirelessRangeResult +{ + + public WirelessRangeResult(TileEntity t, float d) { + dist = d; + te = t; + } + + final public float dist; + final public TileEntity te; + +} diff --git a/core/features/registries/WirelessRegistry.java b/core/features/registries/WirelessRegistry.java new file mode 100644 index 00000000..82d59e62 --- /dev/null +++ b/core/features/registries/WirelessRegistry.java @@ -0,0 +1,71 @@ +package appeng.core.features.registries; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import appeng.api.features.IWirelessTermHandler; +import appeng.api.features.IWirelessTermRegistery; +import appeng.util.Platform; +import cpw.mods.fml.common.network.Player; + +public class WirelessRegistry implements IWirelessTermRegistery +{ + + List handlers; + + public WirelessRegistry() { + handlers = new ArrayList(); + } + + @Override + public void registerWirelessHandler(IWirelessTermHandler handler) + { + handlers.add( handler ); + } + + @Override + public boolean isWirelessTerminal(ItemStack is) + { + for (IWirelessTermHandler h : handlers) + { + if ( h.canHandle( is ) ) + return true; + } + return false; + } + + @Override + public IWirelessTermHandler getWirelessTerminalHandler(ItemStack is) + { + for (IWirelessTermHandler h : handlers) + { + if ( h.canHandle( is ) ) + return h; + } + return null; + } + + @Override + public void OpenWirelessTermainlGui(ItemStack item, World w, EntityPlayer player) + { + if ( Platform.isClient() ) + return; + + IWirelessTermHandler handler = getWirelessTerminalHandler( item ); + if ( handler == null ) + { + player.addChatMessage( "Item is not a wireless terminal." ); + return; + } + + if ( handler.usePower( (Player) player, 10.0f, item ) ) + { + + } + + } + +} diff --git a/core/features/registries/entries/AppEngGrinderRecipe.java b/core/features/registries/entries/AppEngGrinderRecipe.java new file mode 100644 index 00000000..f8bab220 --- /dev/null +++ b/core/features/registries/entries/AppEngGrinderRecipe.java @@ -0,0 +1,88 @@ +package appeng.core.features.registries.entries; + +import net.minecraft.item.ItemStack; +import appeng.api.features.IGrinderEntry; + +public class AppEngGrinderRecipe implements IGrinderEntry +{ + + private ItemStack in; + private ItemStack out; + + private float optionalChance; + private ItemStack optionalOutput; + + private int energy; + + public AppEngGrinderRecipe(ItemStack a, ItemStack b, int cost) { + in = a; + out = b; + energy = cost; + } + + public AppEngGrinderRecipe(ItemStack a, ItemStack b, ItemStack c, float chance, int cost) { + in = a; + out = b; + + optionalOutput = c; + optionalChance = chance; + + energy = cost; + } + + @Override + public ItemStack getInput() + { + return in; + } + + @Override + public void setInput(ItemStack i) + { + in = i.copy(); + } + + @Override + public ItemStack getOutput() + { + return out; + } + + @Override + public void setOutput(ItemStack o) + { + out = o.copy(); + } + + @Override + public int getEnergyCost() + { + return energy; + } + + @Override + public void setEnergyCost(int c) + { + energy = c; + } + + @Override + public ItemStack getOptionalOutput() + { + return optionalOutput; + } + + @Override + public void setOptionalOutput(ItemStack output, float chance) + { + optionalOutput = output; + optionalChance = chance; + } + + @Override + public float getOptionalChance() + { + return optionalChance; + } + +} diff --git a/core/features/registries/entries/BasicCellHandler.java b/core/features/registries/entries/BasicCellHandler.java new file mode 100644 index 00000000..15f7c095 --- /dev/null +++ b/core/features/registries/entries/BasicCellHandler.java @@ -0,0 +1,58 @@ +package appeng.core.features.registries.entries; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import appeng.api.implementations.IChestOrDrive; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.client.texture.ExtraTextures; +import appeng.core.sync.GuiBridge; +import appeng.me.storage.CellInventory; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; + +public class BasicCellHandler implements ICellHandler +{ + + @Override + public boolean isCell(ItemStack is) + { + return CellInventory.isCell( is ); + } + + @Override + public IMEInventoryHandler getCellInventory(ItemStack is, StorageChannel channel) + { + if ( channel == StorageChannel.ITEMS ) + return CellInventory.getCell( is ); + return null; + } + + @Override + public Icon getTopTexture() + { + return ExtraTextures.BlockMEChestItems.getIcon(); + } + + @Override + public void openChestGui(EntityPlayer player, IChestOrDrive chest, ICellHandler cellHandler, IMEInventoryHandler inv, ItemStack is, StorageChannel chan) + { + Platform.openGUI( player, (AEBaseTile) chest, chest.getUp(), GuiBridge.GUI_ME ); + } + + @Override + public int getStatusForCell(ItemStack is, IMEInventory handler) + { + return 1; + } + + @Override + public double cellIdleDrain(ItemStack is, IMEInventory handler) + { + CellInventory inv = (CellInventory) handler; + return inv.getIdleDrain(); + } +} diff --git a/core/features/registries/entries/BasicTerminalHandler.java b/core/features/registries/entries/BasicTerminalHandler.java new file mode 100644 index 00000000..b1593c7e --- /dev/null +++ b/core/features/registries/entries/BasicTerminalHandler.java @@ -0,0 +1,62 @@ +package appeng.core.features.registries.entries; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.AEApi; +import appeng.api.features.IWirelessTermHandler; +import appeng.util.Platform; +import cpw.mods.fml.common.network.Player; + +public class BasicTerminalHandler implements IWirelessTermHandler +{ + + @Override + public boolean canHandle(ItemStack is) + { + if ( is == null ) + return false; + + if ( AEApi.instance().items().itemWirelessTerminal.sameAs( is ) ) + return true; + + return false; + } + + @Override + public boolean usePower(Player player, float amount, ItemStack is) + { + return false; + } + + @Override + public boolean hasPower(Player player, ItemStack is) + { + return false; + } + + @Override + public String getEncryptionKey(ItemStack i) + { + if ( i == null ) + return null; + NBTTagCompound tag = Platform.openNbtData( i ); + if ( tag != null ) + { + return tag.getString( "encKey" ); + } + return null; + } + + @Override + public void setEncryptionKey(ItemStack i, String encKey, String name) + { + if ( i == null ) + return; + NBTTagCompound tag = Platform.openNbtData( i ); + if ( tag != null ) + { + tag.setString( "encKey", encKey ); + } + } + +} diff --git a/core/features/registries/entries/CreativeCellHandler.java b/core/features/registries/entries/CreativeCellHandler.java new file mode 100644 index 00000000..08f38746 --- /dev/null +++ b/core/features/registries/entries/CreativeCellHandler.java @@ -0,0 +1,57 @@ +package appeng.core.features.registries.entries; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatMessageComponent; +import net.minecraft.util.Icon; +import appeng.api.implementations.IChestOrDrive; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.client.texture.ExtraTextures; +import appeng.items.storage.ItemCreativeStorageCell; +import appeng.me.storage.CreativeCellInventory; + +public class CreativeCellHandler implements ICellHandler +{ + + @Override + public boolean isCell(ItemStack is) + { + return is != null && is.getItem() instanceof ItemCreativeStorageCell; + } + + @Override + public IMEInventoryHandler getCellInventory(ItemStack is, StorageChannel channel) + { + if ( channel == StorageChannel.ITEMS && is != null && is.getItem() instanceof ItemCreativeStorageCell ) + return CreativeCellInventory.getCell( is ); + return null; + } + + @Override + public Icon getTopTexture() + { + return ExtraTextures.BlockMEChestItems.getIcon(); + } + + @Override + public void openChestGui(EntityPlayer player, IChestOrDrive chest, ICellHandler cellHandler, IMEInventoryHandler inv, ItemStack is, StorageChannel chan) + { + player.sendChatToPlayer( ChatMessageComponent.createFromText( "Not ready yet..." ) ); + } + + @Override + public int getStatusForCell(ItemStack is, IMEInventory handler) + { + return 2; + } + + @Override + public double cellIdleDrain(ItemStack is, IMEInventory handler) + { + return 0; + } + +} diff --git a/core/localization/GuiText.java b/core/localization/GuiText.java new file mode 100644 index 00000000..3d7966ab --- /dev/null +++ b/core/localization/GuiText.java @@ -0,0 +1,33 @@ +package appeng.core.localization; + +import net.minecraft.util.StatCollector; +import appeng.core.AELog; + +public enum GuiText +{ + inventory("container"), // mc's default Inventory localization. + + Chest, StoredEnergy, Of, Condenser, Drive, GrindStone, VibrationChamber, SpatialIOPort, NetworkStatus, LevelEmitter, Terminal; + + String root; + + GuiText() { + root = "gui.appliedenergistics2"; + AELog.localization( "gui", getName() ); + } + + GuiText(String r) { + root = r; + } + + private String getName() + { + return root + "." + toString(); + } + + public String getLocal() + { + return StatCollector.translateToLocal( getName() ); + } + +} diff --git a/core/localization/PlayerMessages.java b/core/localization/PlayerMessages.java new file mode 100644 index 00000000..1e10137c --- /dev/null +++ b/core/localization/PlayerMessages.java @@ -0,0 +1,24 @@ +package appeng.core.localization; + +import net.minecraft.util.ChatMessageComponent; +import appeng.core.AELog; + +public enum PlayerMessages +{ + ChestCannotReadStorageCell, InvalidMachine, LoadedSettings, SavedSettings, MachineNotPowered; + + private PlayerMessages() { + AELog.localization( "chat", getName() ); + } + + String getName() + { + return "chat.appliedenergistics2." + toString(); + } + + public ChatMessageComponent get() + { + return ChatMessageComponent.createFromTranslationKey( getName() ); + } + +} diff --git a/core/sync/AppEngClientPacketHandler.java b/core/sync/AppEngClientPacketHandler.java new file mode 100644 index 00000000..a4911f0c --- /dev/null +++ b/core/sync/AppEngClientPacketHandler.java @@ -0,0 +1,46 @@ +package appeng.core.sync; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet250CustomPayload; +import cpw.mods.fml.common.network.IPacketHandler; +import cpw.mods.fml.common.network.Player; + +public class AppEngClientPacketHandler extends AppEngPacketHandlerBase implements IPacketHandler +{ + + @Override + public void onPacketData(INetworkManager network, Packet250CustomPayload packet, Player player) + { + DataInputStream stream = new DataInputStream( new ByteArrayInputStream( packet.data ) ); + // Determine packet type and coordinates of affected tile entity + int packetType = -1; + + try + { + packetType = stream.readInt(); + AppEngPacket pack = PacketTypes.getPacket( packetType ).parsePacket( stream ); + pack.clientPacketData( network, pack, player ); + } catch (IOException e) + { + e.printStackTrace(); + } catch (InstantiationException e) + { + e.printStackTrace(); + } catch (IllegalAccessException e) + { + e.printStackTrace(); + } catch (IllegalArgumentException e) + { + e.printStackTrace(); + } catch (InvocationTargetException e) + { + e.printStackTrace(); + } + + } +} diff --git a/core/sync/AppEngConnectionHandler.java b/core/sync/AppEngConnectionHandler.java new file mode 100644 index 00000000..a262b47a --- /dev/null +++ b/core/sync/AppEngConnectionHandler.java @@ -0,0 +1,49 @@ +package appeng.core.sync; + +import net.minecraft.network.INetworkManager; +import net.minecraft.network.NetLoginHandler; +import net.minecraft.network.packet.NetHandler; +import net.minecraft.network.packet.Packet1Login; +import net.minecraft.server.MinecraftServer; +import appeng.core.WorldSettings; +import cpw.mods.fml.common.network.IConnectionHandler; +import cpw.mods.fml.common.network.Player; + +public class AppEngConnectionHandler implements IConnectionHandler +{ + + @Override + public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) + { + WorldSettings.getInstance().sendToPlayer( player ); + } + + @Override + public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) + { + return null; + } + + @Override + public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) + { + } + + @Override + public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) + { + + } + + @Override + public void connectionClosed(INetworkManager manager) + { + + } + + @Override + public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) + { + } + +} diff --git a/core/sync/AppEngPacket.java b/core/sync/AppEngPacket.java new file mode 100644 index 00000000..47fbd67a --- /dev/null +++ b/core/sync/AppEngPacket.java @@ -0,0 +1,43 @@ +package appeng.core.sync; + +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet250CustomPayload; +import appeng.core.Configuration; +import cpw.mods.fml.common.network.Player; + +public abstract class AppEngPacket +{ + + private Packet250CustomPayload p; + protected boolean isChunkDataPacket; + + AppEngPacketHandlerBase.PacketTypes id; + + final public int getPacketID() + { + return AppEngPacketHandlerBase.PacketTypes.getID( this.getClass() ).ordinal(); + } + + public void serverPacketData(INetworkManager manager, AppEngPacket packet, Player player) + { + throw new RuntimeException( "This packet ( " + getPacketID() + " does not implement a server side handler." ); + } + + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + throw new RuntimeException( "This packet ( " + getPacketID() + " does not implement a client side handler." ); + } + + public Packet250CustomPayload getPacket() + { + // / += p.getPacketSize(); + return p; + } + + protected void configureWrite(byte[] par2ArrayOfByte) + { + p = new Packet250CustomPayload( Configuration.PACKET_CHANNEL, par2ArrayOfByte ); + p.isChunkDataPacket = isChunkDataPacket; + } + +} diff --git a/core/sync/AppEngPacketHandlerBase.java b/core/sync/AppEngPacketHandlerBase.java new file mode 100644 index 00000000..4b62b9a5 --- /dev/null +++ b/core/sync/AppEngPacketHandlerBase.java @@ -0,0 +1,86 @@ +package appeng.core.sync; + +import java.io.DataInputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import appeng.core.sync.packets.PacketConfigButton; +import appeng.core.sync.packets.PacketInventoryAction; +import appeng.core.sync.packets.PacketLightning; +import appeng.core.sync.packets.PacketLocalizedChatMsg; +import appeng.core.sync.packets.PacketMEInventoryUpdate; +import appeng.core.sync.packets.PacketMatterCannon; +import appeng.core.sync.packets.PacketMockExplosion; +import appeng.core.sync.packets.PacketMultiPart; +import appeng.core.sync.packets.PacketPartPlacement; + +public class AppEngPacketHandlerBase +{ + + public static Map reverseLookup = new HashMap(); + + public enum PacketTypes + { + PACKET_INVENTORY_ACTION(PacketInventoryAction.class), + + PACKET_ME_INVENTORY_UPDATE(PacketMEInventoryUpdate.class), + + PACKET_CONFIG_BUTTON(PacketConfigButton.class), + + PACKET_MULTIPART(PacketMultiPart.class), + + PACKET_PARTPLACEMENT(PacketPartPlacement.class), + + PACKET_LIGHTNING(PacketLightning.class), + + PACKET_MATTERCANNON(PacketMatterCannon.class), + + PACKET_MOCKEXPLOSION(PacketMockExplosion.class), + + PACKET_LOCALIZED_CHATMSG(PacketLocalizedChatMsg.class); + + final public Class pc; + final public Constructor con; + + private PacketTypes(Class c) { + pc = c; + + Constructor x = null; + try + { + x = pc.getConstructor( DataInputStream.class ); + } + catch (NoSuchMethodException e) + { + } + catch (SecurityException e) + { + } + + con = x; + AppEngPacketHandlerBase.reverseLookup.put( pc, this ); + + if ( con == null ) + throw new RuntimeException( "Invalid Packet Class, must be constructable on DataInputStream" ); + } + + AppEngPacket parsePacket(DataInputStream in) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException + { + return (AppEngPacket) con.newInstance( in ); + } + + public static PacketTypes getPacket(int id) + { + return (values())[id]; + } + + public static PacketTypes getID(Class c) + { + return AppEngPacketHandlerBase.reverseLookup.get( c ); + } + + }; + +} diff --git a/core/sync/AppEngServerPacketHandler.java b/core/sync/AppEngServerPacketHandler.java new file mode 100644 index 00000000..83a40612 --- /dev/null +++ b/core/sync/AppEngServerPacketHandler.java @@ -0,0 +1,46 @@ +package appeng.core.sync; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet250CustomPayload; +import cpw.mods.fml.common.network.IPacketHandler; +import cpw.mods.fml.common.network.Player; + +public final class AppEngServerPacketHandler extends AppEngPacketHandlerBase implements IPacketHandler +{ + + @Override + public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) + { + DataInputStream stream = new DataInputStream( new ByteArrayInputStream( packet.data ) ); + // Determine packet type and coordinates of affected tile entity + int packetType = -1; + + try + { + packetType = stream.readInt(); + AppEngPacket pack = PacketTypes.getPacket( packetType ).parsePacket( stream ); + pack.serverPacketData( manager, pack, player ); + } catch (IOException e) + { + e.printStackTrace(); + } catch (InstantiationException e) + { + e.printStackTrace(); + } catch (IllegalAccessException e) + { + e.printStackTrace(); + } catch (IllegalArgumentException e) + { + e.printStackTrace(); + } catch (InvocationTargetException e) + { + e.printStackTrace(); + } + + } +} diff --git a/core/sync/GuiBridge.java b/core/sync/GuiBridge.java new file mode 100644 index 00000000..281898e7 --- /dev/null +++ b/core/sync/GuiBridge.java @@ -0,0 +1,172 @@ +package appeng.core.sync; + +import java.lang.reflect.Constructor; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.client.gui.GuiNull; +import appeng.container.ContainerNull; +import appeng.container.implementations.ContainerChest; +import appeng.container.implementations.ContainerCondenser; +import appeng.container.implementations.ContainerDrive; +import appeng.container.implementations.ContainerGrinder; +import appeng.container.implementations.ContainerMEMonitorable; +import appeng.container.implementations.ContainerVibrationChamber; +import appeng.tile.grindstone.TileGrinder; +import appeng.tile.misc.TileCondenser; +import appeng.tile.misc.TileVibrationChamber; +import appeng.tile.storage.TileChest; +import appeng.tile.storage.TileDrive; +import appeng.util.Platform; +import cpw.mods.fml.common.network.IGuiHandler; +import cpw.mods.fml.relauncher.ReflectionHelper; + +public enum GuiBridge implements IGuiHandler +{ + GUI_Handler(), + + GUI_GRINDER(ContainerGrinder.class, TileGrinder.class), + + GUI_CHEST(ContainerChest.class, TileChest.class), + + GUI_ME(ContainerMEMonitorable.class, IStorageMonitorable.class), + + GUI_DRIVE(ContainerDrive.class, TileDrive.class), + + GUI_VIBRATIONCHAMBER(ContainerVibrationChamber.class, TileVibrationChamber.class), + + GUI_CONDENSER(ContainerCondenser.class, TileCondenser.class); + + private Class Tile; + private Class Gui; + private Class Container; + + private GuiBridge() { + Tile = null; + Gui = null; + Container = null; + } + + /** + * I honestly wish I could just use the GuiClass Names myself, but I can't access them without MC's Server + * Exploding. + */ + private void getGui() + { + if ( Platform.isClient() ) + { + String start = Container.getName(); + String GuiClass = start.replaceFirst( "container.", "client.gui." ).replace( ".Container", ".Gui" ); + if ( start.equals( GuiClass ) ) + throw new RuntimeException( "Unable to find gui class" ); + Gui = ReflectionHelper.getClass( this.getClass().getClassLoader(), GuiClass ); + if ( Gui == null ) + throw new RuntimeException( "Cannot Load class: " + GuiClass ); + } + } + + private GuiBridge(Class _Container) { + Container = _Container; + Tile = null; + getGui(); + } + + private GuiBridge(Class _Container, Class _Tile) { + Container = _Container; + Tile = _Tile; + getGui(); + } + + public boolean CorrectTileOrPart(Object tE) + { + if ( Tile == null ) + throw new RuntimeException( "This Gui Cannot use the standard Handler." ); + + return Tile.isInstance( tE ); + } + + public Object ConstructContainer(InventoryPlayer inventory, ForgeDirection side, Object tE) + { + try + { + Constructor[] c = Container.getConstructors(); + if ( c.length == 0 ) + throw new AppEngException( "Invalid Gui Class" ); + return c[0].newInstance( inventory, tE ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + public Object ConstructGui(InventoryPlayer inventory,ForgeDirection side, Object tE) + { + try + { + Constructor[] c = Gui.getConstructors(); + if ( c.length == 0 ) + throw new AppEngException( "Invalid Gui Class" ); + return c[0].newInstance( inventory, tE ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + @Override + public Object getServerGuiElement(int ID_ORDINAL, EntityPlayer player, World w, int x, int y, int z) + { + ForgeDirection side = ForgeDirection.getOrientation( ID_ORDINAL& 0x07 ); + GuiBridge ID = values()[ID_ORDINAL >> 3]; + + TileEntity TE = w.getBlockTileEntity( x, y, z ); + + if ( TE instanceof IPartHost ) + { + ((IPartHost) TE).getPart( side ); + IPart part = ((IPartHost) TE).getPart(side); + if ( ID.CorrectTileOrPart(part) ) + return ID.ConstructContainer( player.inventory, side, part ); + } + else + { + if ( ID.CorrectTileOrPart( TE ) ) + return ID.ConstructContainer( player.inventory, side, TE ); + } + + return new ContainerNull(); + } + + @Override + public Object getClientGuiElement(int ID_ORDINAL, EntityPlayer player, World w, int x, int y, int z) + { + ForgeDirection side = ForgeDirection.getOrientation( ID_ORDINAL& 0x07 ); + GuiBridge ID = values()[ID_ORDINAL >> 3]; + + TileEntity TE = w.getBlockTileEntity( x, y, z ); + + if ( TE instanceof IPartHost ) + { + ((IPartHost) TE).getPart( side ); + IPart part = ((IPartHost) TE).getPart(side); + if ( ID.CorrectTileOrPart(part) ) + return ID.ConstructGui( player.inventory, side, part ); + } + else + { + if ( ID.CorrectTileOrPart( TE ) ) + return ID.ConstructGui( player.inventory, side, TE ); + } + + return new GuiNull( new ContainerNull() ); + } + +} diff --git a/core/sync/packets/PacketConfigButton.java b/core/sync/packets/PacketConfigButton.java new file mode 100644 index 00000000..3142e2f8 --- /dev/null +++ b/core/sync/packets/PacketConfigButton.java @@ -0,0 +1,57 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetworkManager; +import net.minecraft.tileentity.TileEntity; +import appeng.api.config.Settings; +import appeng.api.util.IConfigManager; +import appeng.api.util.IConfigureableObject; +import appeng.container.AEBaseContainer; +import appeng.core.sync.AppEngPacket; +import appeng.util.Platform; +import cpw.mods.fml.common.network.Player; + +public class PacketConfigButton extends AppEngPacket +{ + + final public Settings option; + + // automatic. + public PacketConfigButton(DataInputStream stream) throws IOException { + option = Settings.values()[stream.readInt()]; + } + + @Override + public void serverPacketData(INetworkManager manager, AppEngPacket packet, Player player) + { + EntityPlayerMP sender = (EntityPlayerMP) player; + AEBaseContainer aebc = (AEBaseContainer) sender.openContainer; + TileEntity bt = aebc.getTileEntity(); + if ( bt instanceof IConfigureableObject ) + { + IConfigManager cm = ((IConfigureableObject) bt).getConfigManager(); + Enum newState = Platform.nextEnum( cm.getSetting( option ) ); + cm.putSetting( option, newState ); + } + } + + // api + public PacketConfigButton(Settings option) throws IOException { + this.option = option; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeInt( option.ordinal() ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketInventoryAction.java b/core/sync/packets/PacketInventoryAction.java new file mode 100644 index 00000000..98edd8ae --- /dev/null +++ b/core/sync/packets/PacketInventoryAction.java @@ -0,0 +1,68 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetworkManager; +import appeng.api.storage.data.IAEItemStack; +import appeng.container.AEBaseContainer; +import appeng.core.sync.AppEngPacket; +import appeng.helpers.InventoryAction; +import appeng.util.item.AEItemStack; +import cpw.mods.fml.common.network.Player; + +public class PacketInventoryAction extends AppEngPacket +{ + + final public InventoryAction action; + final public int slot; + final public IAEItemStack slotItem; + + // automatic. + public PacketInventoryAction(DataInputStream stream) throws IOException { + action = InventoryAction.values()[stream.readInt()]; + slot = stream.readInt(); + boolean hasItem = stream.readBoolean(); + if ( hasItem ) + slotItem = AEItemStack.loadItemStackFromPacket( stream ); + else + slotItem = null; + } + + @Override + public void serverPacketData(INetworkManager manager, AppEngPacket packet, Player player) + { + EntityPlayerMP sender = (EntityPlayerMP) player; + AEBaseContainer aebc = (AEBaseContainer) sender.openContainer; + aebc.doAction( sender, action, slot, slotItem ); + } + + // api + public PacketInventoryAction(InventoryAction action, int slot, IAEItemStack slotItem) throws IOException { + this.action = action; + this.slot = slot; + this.slotItem = slotItem; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeInt( action.ordinal() ); + data.writeInt( slot ); + + if ( slotItem == null ) + data.writeBoolean( false ); + else + { + data.writeBoolean( true ); + slotItem.writeToPacket( data ); + } + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketLightning.java b/core/sync/packets/PacketLightning.java new file mode 100644 index 00000000..844b693c --- /dev/null +++ b/core/sync/packets/PacketLightning.java @@ -0,0 +1,70 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.network.INetworkManager; +import appeng.client.ClientHelper; +import appeng.client.render.effects.LightningEffect; +import appeng.core.Configuration; +import appeng.core.sync.AppEngPacket; +import appeng.util.Platform; +import cpw.mods.fml.common.network.Player; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class PacketLightning extends AppEngPacket +{ + + final double x; + final double y; + final double z; + + // automatic. + public PacketLightning(DataInputStream stream) throws IOException { + x = stream.readFloat(); + y = stream.readFloat(); + z = stream.readFloat(); + } + + @Override + @SideOnly(Side.CLIENT) + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + try + { + if ( Platform.isClient() && Configuration.instance.enableEffects ) + { + LightningEffect fx = new LightningEffect( ClientHelper.proxy.getWorld(), x, y, z, 0.0f, 0.0f, 0.0f ); + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + } + catch (Exception err) + { + } + } + + // api + public PacketLightning(double x, double y, double z) throws IOException { + + this.x = x; + this.y = y; + this.z = z; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeFloat( (float) x ); + data.writeFloat( (float) y ); + data.writeFloat( (float) z ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketLocalizedChatMsg.java b/core/sync/packets/PacketLocalizedChatMsg.java new file mode 100644 index 00000000..e918f394 --- /dev/null +++ b/core/sync/packets/PacketLocalizedChatMsg.java @@ -0,0 +1,47 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.INetworkManager; +import net.minecraft.util.ChatMessageComponent; +import appeng.core.sync.AppEngPacket; +import cpw.mods.fml.common.network.Player; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class PacketLocalizedChatMsg extends AppEngPacket +{ + + final public String msg; + + // automatic. + public PacketLocalizedChatMsg(DataInputStream stream) throws IOException { + msg = stream.readUTF(); + } + + @Override + @SideOnly(Side.CLIENT) + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + ((EntityPlayer) player).sendChatToPlayer( ChatMessageComponent.createFromTranslationWithSubstitutions( msg ) ); + } + + // api + public PacketLocalizedChatMsg(String msg) throws IOException { + this.msg = msg; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeUTF( msg ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketMEInventoryUpdate.java b/core/sync/packets/PacketMEInventoryUpdate.java new file mode 100644 index 00000000..f10df02f --- /dev/null +++ b/core/sync/packets/PacketMEInventoryUpdate.java @@ -0,0 +1,81 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet250CustomPayload; +import appeng.api.storage.data.IAEItemStack; +import appeng.client.gui.implementations.GuiMEMonitorable; +import appeng.core.sync.AppEngPacket; +import appeng.util.item.AEItemStack; +import cpw.mods.fml.common.network.Player; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class PacketMEInventoryUpdate extends AppEngPacket +{ + + // output... + final private ByteArrayOutputStream bytes; + final private DataOutputStream data; + boolean empty = true; + + // input. + final List list; + + // automatic. + public PacketMEInventoryUpdate(DataInputStream stream) throws IOException { + bytes = null; + data = null; + list = new LinkedList(); + while (stream.available() > 0) + list.add( AEItemStack.loadItemStackFromPacket( stream ) ); + empty = list.isEmpty(); + } + + @Override + @SideOnly(Side.CLIENT) + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + GuiScreen gs = Minecraft.getMinecraft().currentScreen; + if ( gs instanceof GuiMEMonitorable ) + { + ((GuiMEMonitorable) gs).postUpdate( list ); + } + } + + @Override + public Packet250CustomPayload getPacket() + { + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + return super.getPacket(); + } + + // api + public PacketMEInventoryUpdate() throws IOException { + bytes = new ByteArrayOutputStream(); + data = new DataOutputStream( bytes ); + list = null; + data.writeInt( getPacketID() ); + } + + public void appendItem(IAEItemStack is) throws IOException + { + is.writeToPacket( data ); + empty = false; + } + + public boolean isEmpty() + { + return empty; + } + +} diff --git a/core/sync/packets/PacketMatterCannon.java b/core/sync/packets/PacketMatterCannon.java new file mode 100644 index 00000000..7fbb0854 --- /dev/null +++ b/core/sync/packets/PacketMatterCannon.java @@ -0,0 +1,90 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.item.Item; +import net.minecraft.network.INetworkManager; +import net.minecraft.world.World; +import appeng.client.render.effects.MatterCannonEffect; +import appeng.core.sync.AppEngPacket; +import cpw.mods.fml.client.FMLClientHandler; +import cpw.mods.fml.common.network.Player; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class PacketMatterCannon extends AppEngPacket +{ + + final double x; + final double y; + final double z; + final double dx; + final double dy; + final double dz; + final byte len; + + // automatic. + public PacketMatterCannon(DataInputStream stream) throws IOException { + x = stream.readFloat(); + y = stream.readFloat(); + z = stream.readFloat(); + dx = stream.readFloat(); + dy = stream.readFloat(); + dz = stream.readFloat(); + len = stream.readByte(); + } + + @Override + @SideOnly(Side.CLIENT) + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + try + { + + World world = FMLClientHandler.instance().getClient().theWorld; + for (int a = 1; a < len; a++) + { + MatterCannonEffect fx = new MatterCannonEffect( world, x + dx * a, y + dy * a, z + dz * a, Item.diamond ); + + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + } catch (Exception err) + { + } + } + + // api + public PacketMatterCannon(double x, double y, double z, float dx, float dy, float dz, byte len) throws IOException { + float dl = dx * dx + dy * dy + dz * dz; + float dlz = (float) Math.sqrt( dl ); + + this.x = x; + this.y = y; + this.z = z; + this.dx = dx / dlz; + this.dy = dy / dlz; + this.dz = dz / dlz; + this.len = len; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeFloat( (float) x ); + data.writeFloat( (float) y ); + data.writeFloat( (float) z ); + data.writeFloat( (float) this.dx ); + data.writeFloat( (float) this.dy ); + data.writeFloat( (float) this.dz ); + data.writeByte( len ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketMockExplosion.java b/core/sync/packets/PacketMockExplosion.java new file mode 100644 index 00000000..9ecd537f --- /dev/null +++ b/core/sync/packets/PacketMockExplosion.java @@ -0,0 +1,56 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.network.INetworkManager; +import net.minecraft.world.World; +import appeng.core.CommonHelper; +import appeng.core.sync.AppEngPacket; +import cpw.mods.fml.common.network.Player; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class PacketMockExplosion extends AppEngPacket +{ + + final public double x; + final public double y; + final public double z; + + @Override + @SideOnly(Side.CLIENT) + public void clientPacketData(INetworkManager network, AppEngPacket packet, Player player) + { + World world = CommonHelper.proxy.getWorld(); + world.spawnParticle( "largeexplode", this.x, this.y, this.z, 1.0D, 0.0D, 0.0D ); + } + + // automatic. + public PacketMockExplosion(DataInputStream stream) throws IOException { + x = stream.readDouble(); + y = stream.readDouble(); + z = stream.readDouble(); + } + + // api + public PacketMockExplosion(double x, double y, double z) throws IOException { + this.x = x; + this.y = y; + this.z = z; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeDouble( x ); + data.writeDouble( y ); + data.writeDouble( z ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketMultiPart.java b/core/sync/packets/PacketMultiPart.java new file mode 100644 index 00000000..069f2471 --- /dev/null +++ b/core/sync/packets/PacketMultiPart.java @@ -0,0 +1,42 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetworkManager; +import net.minecraftforge.common.MinecraftForge; +import appeng.core.sync.AppEngPacket; +import appeng.integration.modules.helpers.FMPPacketEvent; +import cpw.mods.fml.common.network.Player; + +public class PacketMultiPart extends AppEngPacket +{ + + // automatic. + public PacketMultiPart(DataInputStream stream) throws IOException { + + } + + @Override + public void serverPacketData(INetworkManager manager, AppEngPacket packet, Player player) + { + EntityPlayerMP sender = (EntityPlayerMP) player; + MinecraftForge.EVENT_BUS.post( new FMPPacketEvent( sender ) ); + } + + // api + public PacketMultiPart() throws IOException { + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/core/sync/packets/PacketPartPlacement.java b/core/sync/packets/PacketPartPlacement.java new file mode 100644 index 00000000..b57b0e3b --- /dev/null +++ b/core/sync/packets/PacketPartPlacement.java @@ -0,0 +1,50 @@ +package appeng.core.sync.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetworkManager; +import appeng.core.sync.AppEngPacket; +import appeng.helpers.PartPlacement; +import cpw.mods.fml.common.network.Player; + +public class PacketPartPlacement extends AppEngPacket +{ + + int x, y, z, face; + + // automatic. + public PacketPartPlacement(DataInputStream stream) throws IOException { + x = stream.readInt(); + y = stream.readInt(); + z = stream.readInt(); + face = stream.readByte(); + } + + @Override + public void serverPacketData(INetworkManager manager, AppEngPacket packet, Player player) + { + EntityPlayerMP sender = (EntityPlayerMP) player; + PartPlacement.place( sender.getHeldItem(), x, y, z, face, sender, sender.worldObj, PartPlacement.PlaceType.INTERACT_FIRST_PASS, 0 ); + } + + // api + public PacketPartPlacement(int x, int y, int z, int face) throws IOException { + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + data.writeInt( getPacketID() ); + data.writeInt( x ); + data.writeInt( y ); + data.writeInt( z ); + data.writeByte( face ); + + isChunkDataPacket = false; + configureWrite( bytes.toByteArray() ); + } + +} diff --git a/debug/ToolDebugCard.java b/debug/ToolDebugCard.java new file mode 100644 index 00000000..19d9b59c --- /dev/null +++ b/debug/ToolDebugCard.java @@ -0,0 +1,164 @@ +package appeng.debug; + +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChatMessageComponent; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.core.features.AEFeature; +import appeng.helpers.TickHandler; +import appeng.items.AEBaseItem; +import appeng.me.Grid; +import appeng.me.GridCacheWrapper; +import appeng.me.GridNode; +import appeng.me.cache.TickManagerCache; +import appeng.util.Platform; + +public class ToolDebugCard extends AEBaseItem +{ + + public ToolDebugCard() { + super( ToolDebugCard.class ); + setfeature( EnumSet.of( AEFeature.Creative ) ); + } + + public String timeMeasurement(long nanos) + { + int ms = (int) (nanos / 1000000); + if ( ms <= 0 ) + return nanos + "ns"; + return ms + "ms"; + } + + @Override + public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) + { + if ( Platform.isClient() ) + return false; + + if ( player.isSneaking() ) + { + int grids = 0; + int totalNodes = 0; + long totalOver5Ticks = 0; + + for (Grid g : TickHandler.instance.getGridList()) + { + TickManagerCache tmc = (TickManagerCache) g.getCache( ITickManager.class ); + + for (GridCacheWrapper w : g.getCacheWrappers()) + { + totalOver5Ticks += w.LastFiveTicksTime; + } + + grids++; + for (IGridNode n : g.getNodes()) + { + totalOver5Ticks += tmc.getAvgNanoTime( n ); + totalNodes++; + } + } + outputMsg( player, "Grids: " + grids ); + outputMsg( player, "Total Nodes: " + totalNodes ); + outputMsg( player, "Average Time Used: " + " - " + timeMeasurement( totalOver5Ticks / 5 ) ); + } + else + { + TileEntity te = world.getBlockTileEntity( x, y, z ); + + if ( te instanceof IGridHost ) + { + GridNode node = (GridNode) ((IGridHost) te).getGridNode( ForgeDirection.getOrientation( side ) ); + if ( node != null ) + { + Grid g = node.getInternalGrid(); + IGridNode center = g.getPivot(); + outputMsg( player, "This Node: " + node.toString() ); + outputMsg( player, "Center Node: " + center.toString() ); + + for (GridCacheWrapper w : g.getCacheWrappers()) + { + outputMsg( player, w.getName() + "Tick: " + timeMeasurement( w.LastFiveTicksTime / 5 ) + ", Add: " + + timeMeasurement( w.LastFiveAddNode / 5 ) + ", Rmv: " + timeMeasurement( w.LastFiveRemoveTime / 5 ) ); + } + + TickManagerCache tmc = (TickManagerCache) g.getCache( ITickManager.class ); + for (Class c : g.getMachineClasses()) + { + int o = 0; + long nanos = 0; + for (IGridNode oj : g.getMachines( c )) + { + o++; + nanos += tmc.getAvgNanoTime( oj ); + } + + if ( nanos < 0 ) + { + outputMsg( player, c.getSimpleName() + " - " + o ); + } + else + { + outputMsg( player, c.getSimpleName() + " - " + o + "; " + timeMeasurement( nanos ) ); + } + } + } + else + outputMsg( player, "No Node Available." ); + } + else + outputMsg( player, "Not Networked Block" ); + + if ( te instanceof IPartHost ) + { + IPart center = ((IPartHost) te).getPart( ForgeDirection.UNKNOWN ); + ((IPartHost) te).markForUpdate(); + if ( center != null ) + { + GridNode n = (GridNode) center.getGridNode(); + outputMsg( player, "Node Channels: " + n.usedChannels() ); + for (IGridConnection gc : n.getConnections()) + { + ForgeDirection fd = gc.getDirection( n ); + if ( fd != ForgeDirection.UNKNOWN ) + outputMsg( player, fd.toString() + ": " + gc.getUsedChannels() ); + } + } + } + + if ( te instanceof IAEPowerStorage ) + { + IAEPowerStorage ps = (IAEPowerStorage) te; + outputMsg( player, "Energy: " + ps.getAECurrentPower() + " / " + ps.getAEMaxPower() ); + + if ( te instanceof IGridHost ) + { + IGridNode node = (IGridNode) ((IGridHost) te).getGridNode( ForgeDirection.getOrientation( side ) ); + if ( node != null && node.getGrid() != null ) + { + IEnergyGrid eg = node.getGrid().getCache( IEnergyGrid.class ); + outputMsg( player, "GridEnerg: " + eg.getStoredPower() + " : " + eg.getEnergyDemand( Double.MAX_VALUE ) ); + } + } + } + } + return true; + } + + private void outputMsg(EntityPlayer player, String string) + { + player.sendChatToPlayer( ChatMessageComponent.createFromText( string ) ); + } + +} diff --git a/entity/EntityChargedQuartz.java b/entity/EntityChargedQuartz.java new file mode 100644 index 00000000..1d09c40c --- /dev/null +++ b/entity/EntityChargedQuartz.java @@ -0,0 +1,118 @@ +package appeng.entity; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.client.render.effects.LightningEffect; +import appeng.core.Configuration; +import appeng.util.Platform; + +final public class EntityChargedQuartz extends EntityItem +{ + + int delay = 0; + int transformTime = 0; + + public EntityChargedQuartz(World w) { + super( w ); + } + + public EntityChargedQuartz(World w, double x, double y, double z, ItemStack is) { + super( w, x, y, z, is ); + } + + @Override + public void onUpdate() + { + super.onUpdate(); + + if ( Platform.isClient() && delay++ > 30 && Configuration.instance.enableEffects ) + { + delay = 0; + LightningEffect fx = new LightningEffect( worldObj, posX, posY + 0.3f, posZ, 0.0f, 0.0f, 0.0f ); + Minecraft.getMinecraft().effectRenderer.addEffect( (EntityFX) fx ); + } + + int j = MathHelper.floor_double( this.posX ); + int i = MathHelper.floor_double( this.posY ); + int k = MathHelper.floor_double( this.posZ ); + + Material mat = worldObj.getBlockMaterial( j, i, k ); + if ( Platform.isServer() && mat.isLiquid() ) + { + transformTime++; + if ( transformTime > 60 ) + { + if ( !transform() ) + transformTime = 0; + } + } + else + transformTime = 0; + }; + + public boolean transform() + { + ItemStack item = getEntityItem(); + if ( AEApi.instance().materials().materialCertusQuartzCrystalCharged.sameAs( item ) ) + { + AxisAlignedBB region = AxisAlignedBB.getBoundingBox( posX - 1, posY - 1, posZ - 1, posX + 1, posY + 1, posZ + 1 ); + List l = worldObj.getEntitiesWithinAABBExcludingEntity( this, region ); + + EntityItem redstone = null; + EntityItem netherQuartz = null; + + for (Entity e : l) + { + if ( e instanceof EntityItem && !e.isDead ) + { + ItemStack other = ((EntityItem) e).getEntityItem(); + if ( other != null && other.stackSize > 0 ) + { + if ( Platform.isSameItem( other, new ItemStack( Item.redstone ) ) ) + redstone = (EntityItem) e; + + if ( Platform.isSameItem( other, new ItemStack( Item.netherQuartz ) ) ) + netherQuartz = (EntityItem) e; + } + } + } + + if ( redstone != null && netherQuartz != null ) + { + getEntityItem().stackSize--; + redstone.getEntityItem().stackSize--; + netherQuartz.getEntityItem().stackSize--; + + if ( getEntityItem().stackSize <= 0 ) + setDead(); + + if ( redstone.getEntityItem().stackSize <= 0 ) + redstone.setDead(); + + if ( netherQuartz.getEntityItem().stackSize <= 0 ) + netherQuartz.setDead(); + + List i = new ArrayList(); + i.add( AEApi.instance().materials().materialFluixCrystal.stack( 1 ) ); + + ItemStack Output = AEApi.instance().materials().materialFluixCrystal.stack( 2 ); + worldObj.spawnEntityInWorld( new EntityItem( worldObj, posX, posY, posZ, Output ) ); + + return true; + } + } + return false; + } +} diff --git a/entity/EntitySingularity.java b/entity/EntitySingularity.java new file mode 100644 index 00000000..4842062f --- /dev/null +++ b/entity/EntitySingularity.java @@ -0,0 +1,108 @@ +package appeng.entity; + +import java.util.Date; +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.oredict.OreDictionary; +import appeng.api.AEApi; +import appeng.util.Platform; + +final public class EntitySingularity extends EntityItem +{ + + static private int randTickSeed = 0; + + public EntitySingularity(World w) { + super( w ); + } + + public EntitySingularity(World w, double x, double y, double z, ItemStack is) { + super( w, x, y, z, is ); + } + + @Override + public boolean attackEntityFrom(DamageSource src, float dmg) + { + if ( src.isExplosion() ) + { + doExplosion(); + return false; + } + + return super.attackEntityFrom( src, dmg ); + } + + public void doExplosion() + { + if ( Platform.isClient() ) + return; + + ItemStack item = getEntityItem(); + if ( AEApi.instance().materials().materialSingularity.sameAs( item ) ) + { + AxisAlignedBB region = AxisAlignedBB.getBoundingBox( posX - 4, posY - 4, posZ - 4, posX + 4, posY + 4, posZ + 4 ); + List l = worldObj.getEntitiesWithinAABBExcludingEntity( this, region ); + + for (Entity e : l) + { + if ( e instanceof EntityItem ) + { + ItemStack other = ((EntityItem) e).getEntityItem(); + if ( other != null ) + { + boolean matches = false; + for (ItemStack is : OreDictionary.getOres( "dustEnder" )) + { + if ( OreDictionary.itemMatches( other, is, false ) ) + { + matches = true; + break; + } + } + + // check... other name. + if ( matches == false ) + { + for (ItemStack is : OreDictionary.getOres( "dustEnderPearl" )) + { + if ( OreDictionary.itemMatches( other, is, false ) ) + { + matches = true; + break; + } + } + } + + if ( matches ) + { + while (item.stackSize > 0 && other.stackSize > 0) + { + other.stackSize--; + if ( other.stackSize == 0 ) + e.setDead(); + + ItemStack Output = AEApi.instance().materials().materialQESingularity.stack( 2 ); + NBTTagCompound cmp = Platform.openNbtData( Output ); + cmp.setLong( "freq", (new Date()).getTime() * 100 + (randTickSeed++) % 100 ); + item.stackSize--; + + worldObj.spawnEntityInWorld( new EntitySingularity( worldObj, posX, posY, posZ, Output ) ); + } + + if ( item.stackSize <= 0 ) + setDead(); + } + } + } + } + } + } + +} diff --git a/entity/EntityTinyTNTPrimed.java b/entity/EntityTinyTNTPrimed.java new file mode 100644 index 00000000..1eb63394 --- /dev/null +++ b/entity/EntityTinyTNTPrimed.java @@ -0,0 +1,162 @@ +package appeng.entity; + +import java.io.IOException; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.core.CommonHelper; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.sync.packets.PacketMockExplosion; +import appeng.util.Platform; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; + +import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData; + +final public class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntityAdditionalSpawnData +{ + + public EntityTinyTNTPrimed(World w) { + super( w ); + this.setSize( 0.35F, 0.35F ); + } + + public EntityTinyTNTPrimed(World w, double x, double y, double z, EntityLivingBase ignitor) { + super( w, x, y, z, ignitor ); + this.setSize( 0.55F, 0.55F ); + this.yOffset = this.height / 2.0F; + } + + /** + * Called to update the entity's position/logic. + */ + @Override + public void onUpdate() + { + this.handleWaterMovement(); + + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + this.motionY -= 0.03999999910593033D; + this.moveEntity( this.motionX, this.motionY, this.motionZ ); + this.motionX *= 0.9800000190734863D; + this.motionY *= 0.9800000190734863D; + this.motionZ *= 0.9800000190734863D; + + if ( this.onGround ) + { + this.motionX *= 0.699999988079071D; + this.motionZ *= 0.699999988079071D; + this.motionY *= -0.5D; + } + + if ( this.isInWater() && Platform.isServer() ) // put out the fuse. + { + EntityItem item = new EntityItem( worldObj, this.posX, this.posY, this.posZ, AEApi.instance().blocks().blockTinyTNT.stack( 1 ) ); + item.motionX = motionX; + item.motionY = motionY; + item.motionZ = motionZ; + item.prevPosX = this.prevPosX; + item.prevPosY = this.prevPosY; + item.prevPosZ = this.prevPosZ; + worldObj.spawnEntityInWorld( item ); + this.setDead(); + } + + if ( this.fuse-- <= 0 ) + { + this.setDead(); + + if ( !this.worldObj.isRemote ) + { + this.explode(); + } + } + else + { + this.worldObj.spawnParticle( "smoke", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D ); + } + } + + // override :P + void explode() + { + this.worldObj.playSoundEffect( this.posX, this.posY, this.posZ, "random.explode", 4.0F, + (1.0F + (this.worldObj.rand.nextFloat() - this.worldObj.rand.nextFloat()) * 0.2F) * 32.9F ); + + if ( this.isInWater() ) + { + return; + } + + if ( Configuration.instance.isFeatureEnabled( AEFeature.TinyTNTBlockDamage ) ) + { + posY -= 0.25; + + for (int x = (int) (posX - 2); x <= posX + 2; x++) + { + for (int y = (int) (posY - 2); y <= posY + 2; y++) + { + for (int z = (int) (posZ - 2); z <= posZ + 2; z++) + { + int l = worldObj.getBlockId( x, y, z ); + Block block = Block.blocksList[l]; + if ( block != null && !block.isAirBlock( worldObj, x, y, z ) ) + { + float strength = (float) (2.3f - (((x + 0.5f) - posX) * ((x + 0.5f) - posX) + ((y + 0.5f) - posY) * ((y + 0.5f) - posY) + ((z + 0.5f) - posZ) + * ((z + 0.5f) - posZ))); + + float resistance = block.getExplosionResistance( this, worldObj, x, y, z, posX, posY, posZ ); + strength -= (resistance + 0.3F) * 0.11f; + if ( strength > 0.01 ) + { + worldObj.destroyBlock( x, y, z, true ); + } + } + } + } + } + } + + try + { + CommonHelper.proxy.sendToAllNearExcept( null, posX, posY, posZ, 64, this.worldObj, (new PacketMockExplosion( posX, posY, posZ )).getPacket() ); + } + catch (IOException e1) + { + } + + for (Object e : this.worldObj.getEntitiesWithinAABBExcludingEntity( this, + AxisAlignedBB.getBoundingBox( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 ) )) + { + if ( e instanceof Entity ) + { + ((Entity) e).attackEntityFrom( DamageSource.setExplosionSource( null ), 6 ); + } + + } + } + + @Override + public void writeSpawnData(ByteArrayDataOutput data) + { + data.writeByte( fuse ); + } + + @Override + public void readSpawnData(ByteArrayDataInput data) + { + fuse = data.readByte(); + } + +} diff --git a/facade/FacadeContainer.java b/facade/FacadeContainer.java new file mode 100644 index 00000000..dfa0ea17 --- /dev/null +++ b/facade/FacadeContainer.java @@ -0,0 +1,162 @@ +package appeng.facade; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IFacadePart; +import appeng.api.parts.IPartHost; +import appeng.core.AppEng; +import appeng.integration.abstraction.IBC; +import appeng.items.parts.ItemFacade; + +public class FacadeContainer implements IFacadeContainer +{ + + final private IFacadePart facades[] = new FacadePart[6]; + + public void writeToStream(DataOutputStream out) throws IOException + { + int facadeSides = 0; + for (int x = 0; x < facades.length; x++) + { + if ( getFacade( ForgeDirection.getOrientation( x ) ) != null ) + facadeSides = facadeSides | (1 << x); + } + out.writeByte( (byte) facadeSides ); + + for (int x = 0; x < facades.length; x++) + { + IFacadePart part = getFacade( ForgeDirection.getOrientation( x ) ); + if ( part != null ) + { + int itemID = part.getItem().itemID; + int dmgValue = part.getItemDamage(); + out.writeInt( itemID * (part.isBC() ? -1 : 1) ); + out.writeInt( dmgValue ); + } + } + } + + public boolean readFromStream(DataInputStream out) throws IOException + { + int facadeSides = out.readByte(); + + int ids[] = new int[2]; + for (int x = 0; x < facades.length; x++) + { + ForgeDirection side = ForgeDirection.getOrientation( x ); + int ix = (1 << x); + if ( (facadeSides & ix) == ix ) + { + ids[0] = out.readInt(); + ids[1] = out.readInt(); + boolean isBC = ids[0] < 0; + ids[0] = Math.abs( ids[0] ); + + if ( isBC && AppEng.instance.isIntegrationEnabled( "BC" ) ) + { + IBC bc = (IBC) AppEng.instance.getIntegration( "BC" ); + facades[x] = bc.createFacadePart( ids, side ); + } + else if ( !isBC ) + { + ItemFacade ifa = (ItemFacade) AEApi.instance().items().itemFacade.item(); + ItemStack facade = ifa.createFromInts( ids ); + if ( facade != null ) + facades[x] = ifa.createPartFromItemStack( facade, side ); + } + } + else + facades[x] = null; + } + return false; + } + + public void readFromNBT(NBTTagCompound c) + { + for (int x = 0; x < facades.length; x++) + { + facades[x] = null; + + NBTTagCompound t = c.getCompoundTag( "facade:" + x ); + if ( t != null ) + { + ItemStack is = ItemStack.loadItemStackFromNBT( t ); + if ( is != null ) + { + Item i = is.getItem(); + if ( i instanceof IFacadeItem ) + facades[x] = ((IFacadeItem) i).createPartFromItemStack( is, ForgeDirection.getOrientation( x ) ); + else + { + if ( AppEng.instance.isIntegrationEnabled( "BC" ) ) + { + IBC bc = (IBC) AppEng.instance.getIntegration( "BC" ); + if ( bc.isFacade( is ) ) + facades[x] = bc.createFacadePart( is, ForgeDirection.getOrientation( x ) ); + } + } + } + } + } + } + + public void writeToNBT(NBTTagCompound c) + { + for (int x = 0; x < facades.length; x++) + { + if ( facades[x] != null ) + { + NBTTagCompound data = new NBTTagCompound(); + facades[x].getItemStack().writeToNBT( data ); + c.setCompoundTag( "facade:" + x, data ); + } + } + } + + @Override + public boolean addFacade(IFacadePart a) + { + if ( getFacade( a.getSide() ) == null ) + { + facades[a.getSide().ordinal()] = a; + return true; + } + return false; + } + + @Override + public void removeFacade(IPartHost host, ForgeDirection side) + { + if ( side != null && side != ForgeDirection.UNKNOWN ) + { + if ( facades[side.ordinal()] != null ) + { + facades[side.ordinal()] = null; + if ( host != null ) + host.markForUpdate(); + } + } + } + + @Override + public IFacadePart getFacade(ForgeDirection s) + { + return facades[s.ordinal()]; + } + + public boolean isEmpty() + { + for (int x = 0; x < facades.length; x++) + if ( facades[x] != null ) + return false; + return true; + } +} diff --git a/facade/FacadePart.java b/facade/FacadePart.java new file mode 100644 index 00000000..5cfcbf42 --- /dev/null +++ b/facade/FacadePart.java @@ -0,0 +1,395 @@ +package appeng.facade; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IFacadePart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.render.BusRenderHelper; +import appeng.client.render.RenderBlocksWorkaround; +import appeng.core.AppEng; +import appeng.integration.abstraction.IBC; + +public class FacadePart implements IFacadePart +{ + + public final ItemStack facade; + public final ForgeDirection side; + + public FacadePart(ItemStack facade, ForgeDirection side) { + if ( facade == null ) + throw new RuntimeException( "Facade Part constructed on null item." ); + facade.stackSize = 1; + this.facade = facade; + this.side = side; + } + + @Override + public ItemStack getItemStack() + { + return facade; + } + + @Override + public void getBoxes(IPartCollsionHelper ch) + { + ch.addBox( 0.0, 0.0, 14, 16.0, 16.0, 16.0 ); + } + + public static boolean isFacade(ItemStack is) + { + if ( is.getItem() instanceof IFacadeItem ) + return true; + return false; + } + + ItemStack getTexture() + { + if ( facade.getItem() instanceof IFacadeItem ) + { + IFacadeItem fi = (IFacadeItem) facade.getItem(); + return fi.getTextureItem( facade ); + } + else if ( AppEng.instance.isIntegrationEnabled( "BC" ) ) + { + IBC bc = (IBC) AppEng.instance.getIntegration( "BC" ); + return bc.getTextureForFacade( facade ); + } + return null; + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper instance2, RenderBlocks renderer, IFacadeContainer fc, AxisAlignedBB busBounds, + boolean renderStilt) + { + if ( facade != null ) + { + BusRenderHelper instance = (BusRenderHelper) instance2; + + try + { + ItemStack randomItem = getTexture(); + + if ( renderStilt && busBounds == null ) + { + if ( renderer instanceof RenderBlocksWorkaround ) + { + RenderBlocksWorkaround rbw = (RenderBlocksWorkaround) renderer; + rbw.isFacade = false; + rbw.calculations = true; + } + + Icon myIcon = null; + if ( isBC() ) + { + IBC bc = (IBC) AppEng.instance.getIntegration( "BC" ); + myIcon = bc.getFacadeTexture(); + } + + if ( myIcon == null ) + myIcon = facade.getIconIndex(); + + instance.setTexture( myIcon ); + + if ( isBC() ) + instance.setBounds( 6, 6, 10, 10, 10, 14 ); + else + instance.setBounds( 7, 7, 10, 9, 9, 14 ); + + instance.renderBlock( x, y, z, renderer ); + instance.setTexture( null ); + + } + + if ( randomItem != null ) + { + if ( randomItem.getItem() instanceof ItemBlock ) + { + ItemBlock ib = (ItemBlock) randomItem.getItem(); + Block blk = Block.blocksList[ib.getBlockID()]; + + try + { + int color = ib.getColorFromItemStack( randomItem, 0 ); + Tessellator.instance.setColorOpaque_I( color ); + } + catch (Throwable error) + { + } + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + instance.setBounds( 0, 0, 14, 16, 16, 16 ); + instance.prepareBounds( renderer ); + + if ( renderer instanceof RenderBlocksWorkaround ) + { + RenderBlocksWorkaround rbw = (RenderBlocksWorkaround) renderer; + + rbw.isFacade = true; + + rbw.calculations = true; + rbw.faces = EnumSet.noneOf( ForgeDirection.class ); + + rbw.renderStandardBlock( blk, x, y, z ); + + rbw.calculations = false; + rbw.faces = EnumSet.allOf( ForgeDirection.class ); + + ((RenderBlocksWorkaround) renderer).setTexture( blk.getIcon( side.ordinal(), ib.getMetadata( randomItem.getItemDamage() ) ) ); + } + else + { + instance.setTexture( blk.getIcon( side.ordinal(), ib.getMetadata( randomItem.getItemDamage() ) ) ); + } + + if ( busBounds == null ) + { + if ( side == ForgeDirection.UP || side == ForgeDirection.DOWN ) + { + instance.renderBlockCurrentBounds( x, y, z, renderer ); + } + else if ( side == ForgeDirection.NORTH || side == ForgeDirection.SOUTH ) + { + if ( fc.getFacade( ForgeDirection.UP ) != null ) + renderer.renderMaxY -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.DOWN ) != null ) + renderer.renderMinY += 2.0 / 16.0; + + instance.renderBlockCurrentBounds( x, y, z, renderer ); + } + else + { + if ( fc.getFacade( ForgeDirection.UP ) != null ) + renderer.renderMaxY -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.DOWN ) != null ) + renderer.renderMinY += 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.SOUTH ) != null ) + renderer.renderMaxZ -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.NORTH ) != null ) + renderer.renderMinZ += 2.0 / 16.0; + + instance.renderBlockCurrentBounds( x, y, z, renderer ); + } + } + else + { + if ( side == ForgeDirection.UP || side == ForgeDirection.DOWN ) + { + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, busBounds.maxZ, 1.0, 1.0, 1.0 ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, 0.0, 1.0, 1.0, busBounds.minZ ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, busBounds.minZ, busBounds.minX, 1.0, busBounds.maxZ ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, busBounds.maxX, 0.0, busBounds.minZ, 1.0, 1.0, busBounds.maxZ ); + } + else if ( side == ForgeDirection.NORTH || side == ForgeDirection.SOUTH ) + { + if ( fc.getFacade( ForgeDirection.UP ) != null ) + renderer.renderMaxY -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.DOWN ) != null ) + renderer.renderMinY += 2.0 / 16.0; + + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, busBounds.maxX, 0.0, 0.0, 1.0, 1.0, 1.0 ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, 0.0, busBounds.minX, 1.0, 1.0 ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, busBounds.minX, 0.0, 0.0, busBounds.maxX, busBounds.minY, 1.0 ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, busBounds.minX, busBounds.maxY, 0.0, busBounds.maxX, 1.0, 1.0 ); + } + else + { + if ( fc.getFacade( ForgeDirection.UP ) != null ) + renderer.renderMaxY -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.DOWN ) != null ) + renderer.renderMinY += 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.SOUTH ) != null ) + renderer.renderMaxZ -= 2.0 / 16.0; + + if ( fc.getFacade( ForgeDirection.NORTH ) != null ) + renderer.renderMinZ += 2.0 / 16.0; + + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, busBounds.maxZ, 1.0, 1.0, 1.0 ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, 0.0, 1.0, 1.0, busBounds.minZ ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, 0.0, busBounds.minZ, 1.0, busBounds.minY, busBounds.maxZ ); + renderSegmentBlockCurrentBounds( instance, x, y, z, renderer, 0.0, busBounds.maxY, busBounds.minZ, 1.0, 1.0, busBounds.maxZ ); + } + } + + instance.setTexture( null ); + Tessellator.instance.setColorOpaque_F( 1, 1, 1 ); + + return; + } + } + } + catch (Throwable t) + { + t.printStackTrace(); + + } + + return; + } + } + + private void renderSegmentBlockCurrentBounds(BusRenderHelper instance, int x, int y, int z, RenderBlocks renderer, double minX, double minY, double minZ, + double maxX, double maxY, double maxZ) + { + double oldMinX = renderer.renderMinX; + double oldMinY = renderer.renderMinY; + double oldMinZ = renderer.renderMinZ; + double oldMaxX = renderer.renderMaxX; + double oldMaxY = renderer.renderMaxY; + double oldMaxZ = renderer.renderMaxZ; + + renderer.renderMinX = Math.max( renderer.renderMinX, minX ); + renderer.renderMinY = Math.max( renderer.renderMinY, minY ); + renderer.renderMinZ = Math.max( renderer.renderMinZ, minZ ); + renderer.renderMaxX = Math.min( renderer.renderMaxX, maxX ); + renderer.renderMaxY = Math.min( renderer.renderMaxY, maxY ); + renderer.renderMaxZ = Math.min( renderer.renderMaxZ, maxZ ); + + // don't draw it if its not at least a pixel wide... + if ( renderer.renderMaxX - renderer.renderMinX >= 1.0 / 16.0 && renderer.renderMaxY - renderer.renderMinY >= 1.0 / 16.0 + && renderer.renderMaxZ - renderer.renderMinZ >= 1.0 / 16.0 ) + { + instance.renderBlockCurrentBounds( x, y, z, renderer ); + } + + renderer.renderMinX = oldMinX; + renderer.renderMinY = oldMinY; + renderer.renderMinZ = oldMinZ; + renderer.renderMaxX = oldMaxX; + renderer.renderMaxY = oldMaxY; + renderer.renderMaxZ = oldMaxZ; + } + + @Override + public void renderInventory(IPartRenderHelper instance, RenderBlocks renderer) + { + if ( facade != null ) + { + IFacadeItem fi = (IFacadeItem) facade.getItem(); + + try + { + ItemStack randomItem = fi.getTextureItem( facade ); + + instance.setTexture( facade.getIconIndex() ); + instance.setBounds( 7, 7, 4, 9, 9, 14 ); + instance.renderInventoryBox( renderer ); + instance.setTexture( null ); + + if ( randomItem != null ) + { + if ( randomItem.getItem() instanceof ItemBlock ) + { + ItemBlock ib = (ItemBlock) randomItem.getItem(); + Block blk = Block.blocksList[ib.getBlockID()]; + + try + { + int color = ib.getColorFromItemStack( randomItem, 0 ); + float r = (color >> 16 & 0xff) / 255F; + float g = (color >> 8 & 0xff) / 255F; + float b = (color & 0xff) / 255F; + GL11.glColor4f( r, g, b, 1.0F ); + } + catch (Throwable error) + { + } + + GL11.glColor4f( 1, 1, 1, 1.0F ); + Tessellator.instance.setBrightness( 15 << 20 | 15 << 4 ); + Tessellator.instance.setColorOpaque_F( 1, 1, 1 ); + instance.setTexture( blk.getIcon( side.ordinal(), ib.getMetadata( randomItem.getItemDamage() ) ) ); + + instance.setBounds( 0, 0, 14, 16, 16, 16 ); + instance.renderInventoryBox( renderer ); + + instance.setTexture( null ); + GL11.glColor4f( 1.0f, 1.0f, 1.0f, 1.0F ); + + return; + } + } + } + catch (Throwable t) + { + + } + + return; + } + } + + @Override + public ForgeDirection getSide() + { + return side; + } + + @Override + public AxisAlignedBB getPrimaryBox() + { + switch (side) + { + case DOWN: + return AxisAlignedBB.getBoundingBox( 0.0, 0.0, 0.0, 1.0, 2.0 / 16.0, 1.0 ); + case EAST: + return AxisAlignedBB.getBoundingBox( 14.0 / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0 ); + case NORTH: + return AxisAlignedBB.getBoundingBox( 0.0, 0.0, 0.0, 1.0, 1.0, 2.0 / 16.0 ); + case SOUTH: + return AxisAlignedBB.getBoundingBox( 0.0, 0.0, 14.0 / 16.0, 1.0, 1.0, 1.0 ); + case UP: + return AxisAlignedBB.getBoundingBox( 0.0, 14.0 / 16.0, 0.0, 1.0, 1.0, 1.0 ); + case WEST: + return AxisAlignedBB.getBoundingBox( 0.0, 0.0, 0.0, 2.0 / 16.0, 1.0, 1.0 ); + default: + break; + + } + return AxisAlignedBB.getBoundingBox( 0, 0, 0, 1, 1, 1 ); + } + + @Override + public Item getItem() + { + ItemStack is = getTexture(); + if ( is == null ) + return null; + return is.getItem(); + } + + @Override + public int getItemDamage() + { + ItemStack is = getTexture(); + if ( is == null ) + return 0; + return is.getItemDamage(); + } + + @Override + public boolean isBC() + { + return !(facade.getItem() instanceof IFacadeItem); + } +} diff --git a/facade/IFacadeItem.java b/facade/IFacadeItem.java new file mode 100644 index 00000000..9d706425 --- /dev/null +++ b/facade/IFacadeItem.java @@ -0,0 +1,18 @@ +package appeng.facade; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; + +public interface IFacadeItem +{ + + FacadePart createPartFromItemStack(ItemStack is, ForgeDirection side); + + ItemStack getTextureItem(ItemStack is); + + int getMeta(ItemStack is); + + Block getBlock(ItemStack is); + +} diff --git a/fmp/CableBusPart.java b/fmp/CableBusPart.java new file mode 100644 index 00000000..5c0b58cc --- /dev/null +++ b/fmp/CableBusPart.java @@ -0,0 +1,436 @@ +package appeng.fmp; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartItem; +import appeng.api.parts.SelectedPart; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.helpers.AEMultiTile; +import appeng.parts.BusCollisionHelper; +import appeng.parts.CableBusContainer; +import appeng.tile.networking.TileCableBus; +import appeng.util.Platform; +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.lighting.LazyLightMatrix; +import codechicken.lib.raytracer.IndexedCuboid6; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import codechicken.multipart.IRedstonePart; +import codechicken.multipart.JCuboidPart; +import codechicken.multipart.JNormalOcclusion; +import codechicken.multipart.NormalOcclusionTest; +import codechicken.multipart.NormallyOccludedPart; +import codechicken.multipart.TMultiPart; + +//TFacePart, +public class CableBusPart extends JCuboidPart implements JNormalOcclusion, IRedstonePart, IPartHost, AEMultiTile +{ + + final static Cuboid6 sideTests[] = new Cuboid6[] { + + new Cuboid6( 6.0 / 16.0, 0, 6.0 / 16.0, 10.0 / 16.0, 6.0 / 16.0, 10.0 / 16.0 ), // DOWN(0, -1, 0), + + new Cuboid6( 6.0 / 16.0, 10.0 / 16.0, 6.0 / 16.0, 10.0 / 16.0, 1.0, 10.0 / 16.0 ), // UP(0, 1, 0), + + new Cuboid6( 6.0 / 16.0, 6.0 / 16.0, 0.0, 10.0 / 16.0, 10.0 / 16.0, 6.0 / 16.0 ),// NORTH(0, 0, -1), + + new Cuboid6( 6.0 / 16.0, 6.0 / 16.0, 10.0 / 16.0, 10.0 / 16.0, 10.0 / 16.0, 1.0 ),// SOUTH(0, 0, 1), + + new Cuboid6( 0.0, 6.0 / 16.0, 6.0 / 16.0, 6.0 / 16.0, 10.0 / 16.0, 10.0 / 16.0 ),// WEST(-1, 0, 0), + + new Cuboid6( 10.0 / 16.0, 6.0 / 16.0, 6.0 / 16.0, 1.0, 10.0 / 16.0, 10.0 / 16.0 ),// EAST(1, 0, 0), + }; + + public CableBusContainer cb = new CableBusContainer( this ); + + @Override + public boolean doesTick() + { + return false; + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return cb.getCableConnectionType( dir ); + } + + @Override + public AEColor getColor() + { + return cb.getColor(); + } + + @Override + public void save(NBTTagCompound tag) + { + cb.writeToNBT( tag ); + } + + @Override + public void load(NBTTagCompound tag) + { + cb.readFromNBT( tag ); + } + + @Override + public void writeDesc(MCDataOutput packet) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream stream = new DataOutputStream( bytes ); + + try + { + cb.writeToStream( stream ); + packet.writeInt( bytes.size() ); + packet.writeByteArray( bytes.toByteArray() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + + } + + @Override + public void readDesc(MCDataInput packet) + { + int len = packet.readInt(); + byte data[] = packet.readByteArray( len ); + + DataInputStream stream = new DataInputStream( new ByteArrayInputStream( data ) ); + + try + { + cb.readFromStream( stream ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + public Cuboid6 getBounds() + { + AxisAlignedBB b = null; + + for (AxisAlignedBB bx : cb.getSelectedBoundingBoxsFromPool( false )) + { + if ( b == null ) + b = bx; + else + { + double minX = Math.min( b.minX, bx.minX ); + double minY = Math.min( b.minY, bx.minY ); + double minZ = Math.min( b.minZ, bx.minZ ); + double maxX = Math.max( b.maxX, bx.maxX ); + double maxY = Math.max( b.maxY, bx.maxY ); + double maxZ = Math.max( b.maxZ, bx.maxZ ); + b.setBounds( minX, minY, minZ, maxX, maxY, maxZ ); + } + } + + if ( b == null ) + return new Cuboid6( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 ); + + return new Cuboid6( b.minX, b.minY, b.minZ, b.maxX, b.maxY, b.maxZ ); + } + + @Override + public String getType() + { + return PartRegistry.CableBusPart.getName(); + } + + @Override + public void onPartChanged(TMultiPart part) + { + cb.updateConnections(); + } + + @Override + public ItemStack pickItem(MovingObjectPosition hit) + { + Vec3 v3 = hit.hitVec.addVector( -hit.blockX, -hit.blockY, -hit.blockZ ); + SelectedPart sp = cb.selectPart( v3 ); + if ( sp != null ) + { + if ( sp.part != null ) + return sp.part.getItemStack( false ); + if ( sp.facade != null ) + return sp.facade.getItemStack(); + } + return null; + } + + @Override + public Iterable getDrops() + { + return cb.getDrops( new ArrayList() ); + } + + @Override + public void onEntityCollision(Entity entity) + { + cb.onEntityCollision( entity ); + } + + @Override + public void onWorldJoin() + { + canUpdate = true; + cb.updateConnections(); + cb.addToWorld(); + } + + @Override + public void onWorldSeparate() + { + canUpdate = false; + cb.removeFromWorld(); + }; + + @Override + public boolean canConnectRedstone(int side) + { + return cb.canConnectRedstone( ForgeDirection.getOrientation( side ) ); + } + + @Override + public int strongPowerLevel(int side) + { + return cb.isProvidingStrongPower( ForgeDirection.getOrientation( side ) ); + } + + @Override + public int weakPowerLevel(int side) + { + return cb.isProvidingWeakPower( ForgeDirection.getOrientation( side ) ); + } + + @Override + public void onNeighborChanged() + { + cb.onNeighborChanged(); + } + + @Override + public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack item) + { + return cb.activate( player, hit.hitVec.addVector( -hit.blockX, -hit.blockY, -hit.blockZ ) ); + } + + @Override + public void renderDynamic(Vector3 pos, float frame, int pass) + { + if ( pass == 0 ) + { + cb.renderDynamic( pos.x, pos.y, pos.z ); + } + } + + @Override + public void renderStatic(Vector3 pos, LazyLightMatrix olm, int pass) + { + if ( pass == 0 ) + { + cb.renderStatic( pos.x, pos.y, pos.z ); + } + } + + @Override + public int getLightValue() + { + return cb.getLightValue(); + } + + @Override + public boolean canAddPart(ItemStack is, ForgeDirection side) + { + if ( is.getItem() instanceof IPartItem ) + { + IPartItem bi = (IPartItem) is.getItem(); + + is = is.copy(); + is.stackSize = 1; + + IPart bp = bi.createPartFromItemStack( is ); + if ( !(side == null || side == ForgeDirection.UNKNOWN || tile() == null) ) + { + List boxes = new ArrayList(); + IPartCollsionHelper bch = new BusCollisionHelper( boxes, side ); + bp.getBoxes( bch ); + for (AxisAlignedBB bb : boxes) + { + if ( !tile().canAddPart( new NormallyOccludedPart( new Cuboid6( bb ) ) ) ) + { + return false; + } + } + } + } + + return cb.canAddPart( is, side ); + } + + @Override + public ForgeDirection addPart(ItemStack is, ForgeDirection side) + { + return cb.addPart( is, side ); + } + + @Override + public IPart getPart(ForgeDirection side) + { + return cb.getPart( side ); + } + + @Override + public void removePart(ForgeDirection side) + { + cb.removePart( side ); + } + + boolean canUpdate = false; + + @Override + public void markForUpdate() + { + if ( Platform.isServer() && canUpdate ) + sendDescUpdate(); + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( getTile() ); + } + + @Override + public void invalidateConvertedTile() + { + cb.setHost( this ); + } + + public void convertFromTile(TileEntity blockTileEntity) + { + TileCableBus tcb = (TileCableBus) blockTileEntity; + cb = tcb.cb; + } + + @Override + public boolean occlusionTest(TMultiPart npart) + { + return NormalOcclusionTest.apply( this, npart ); + } + + @Override + public Iterable getCollisionBoxes() + { + LinkedList l = new LinkedList(); + for (AxisAlignedBB b : cb.getSelectedBoundingBoxsFromPool( false )) + { + l.add( new Cuboid6( b.minX, b.minY, b.minZ, b.maxX, b.maxY, b.maxZ ) ); + } + return l; + + } + + @Override + public Iterable getSubParts() + { + LinkedList l = new LinkedList(); + for (Cuboid6 c : getCollisionBoxes()) + { + l.add( new IndexedCuboid6( 0, c ) ); + } + return l; + } + + @Override + public Iterable getOcclusionBoxes() + { + LinkedList l = new LinkedList(); + for (AxisAlignedBB b : cb.getSelectedBoundingBoxsFromPool( true )) + { + l.add( new Cuboid6( b.minX, b.minY, b.minZ, b.maxX, b.maxY, b.maxZ ) ); + } + return l; + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return cb.getGridNode( dir ); + } + + @Override + public IFacadeContainer getFacadeContainer() + { + return cb.getFacadeContainer(); + } + + @Override + public void clearContainer() + { + cb = new CableBusContainer( this ); + } + + @Override + public boolean isBlocked(ForgeDirection side) + { + if ( side == null || side == ForgeDirection.UNKNOWN || tile() == null ) + return false; + return !tile().canAddPart( new NormallyOccludedPart( sideTests[side.ordinal()] ) ); + } + + @Override + public SelectedPart selectPart(Vec3 pos) + { + return cb.selectPart( pos ); + } + + @Override + public void PartChanged() + { + // nothing! + } + + @Override + public void markForSave() + { + this.getTile().onInventoryChanged(); + } + + @Override + public boolean hasRedstone(ForgeDirection side) + { + return cb.hasRedstone( side ); + } + +} diff --git a/fmp/FMPEvent.java b/fmp/FMPEvent.java new file mode 100644 index 00000000..a2fb9e05 --- /dev/null +++ b/fmp/FMPEvent.java @@ -0,0 +1,139 @@ +package appeng.fmp; + +import java.io.IOException; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockFence; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.Packet15Place; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; +import appeng.block.AEBaseItemBlock; +import appeng.core.sync.packets.PacketMultiPart; +import appeng.integration.modules.helpers.FMPPacketEvent; +import codechicken.lib.packet.PacketCustom; +import codechicken.lib.raytracer.RayTracer; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Vector3; +import codechicken.multipart.TMultiPart; +import codechicken.multipart.TileMultipart; +import cpw.mods.fml.common.network.PacketDispatcher; + +/** + * Basically a total rip of of the FMP version for vanilla, seemed to work well enough... + */ +public class FMPEvent +{ + + private ThreadLocal placing = new ThreadLocal(); + + @ForgeSubscribe + public void ServerFMPEvent(FMPPacketEvent event) + { + FMPEvent.place( event.sender, event.sender.worldObj ); + } + + @ForgeSubscribe + public void playerInteract(PlayerInteractEvent event) + { + if ( event.action == Action.RIGHT_CLICK_BLOCK && event.entityPlayer.worldObj.isRemote ) + { + if ( placing.get() != null ) + return; + placing.set( event ); + if ( place( event.entityPlayer, event.entityPlayer.worldObj ) ) + event.setCanceled( true ); + placing.set( null ); + } + } + + public static boolean place(EntityPlayer player, World world) + { + MovingObjectPosition hit = RayTracer.reTrace( world, player ); + if ( hit == null ) + return false; + + BlockCoord pos = new BlockCoord( hit.blockX, hit.blockY, hit.blockZ ).offset( hit.sideHit ); + ItemStack held = player.getHeldItem(); + TMultiPart part = null; + + Block blk = null; + + if ( held == null ) + return false; + + if ( held.getItem() instanceof AEBaseItemBlock ) + { + AEBaseItemBlock ib = (AEBaseItemBlock) held.getItem(); + blk = Block.blocksList[ib.getBlockID()]; + part = PartRegistry.getPartByBlock( blk, hit.sideHit ); + } + + if ( part == null ) + return false; + + if ( world.isRemote && !player.isSneaking() )// attempt to use block activated like normal and tell the server + // the right stuff + { + Vector3 f = new Vector3( hit.hitVec ).add( -hit.blockX, -hit.blockY, -hit.blockZ ); + Block block = Block.blocksList[world.getBlockId( hit.blockX, hit.blockY, hit.blockZ )]; + if ( block != null && !ignoreActivate( block ) + && block.onBlockActivated( world, hit.blockX, hit.blockY, hit.blockZ, player, hit.sideHit, (float) f.x, (float) f.y, (float) f.z ) ) + { + player.swingItem(); + PacketCustom.sendToServer( new Packet15Place( hit.blockX, hit.blockY, hit.blockZ, hit.sideHit, player.inventory.getCurrentItem(), (float) f.x, + (float) f.y, (float) f.z ) ); + return false; + } + } + + TileMultipart tile = TileMultipart.getOrConvertTile( world, pos ); + if ( tile == null || !tile.canAddPart( part ) ) + return false; + + if ( !world.isRemote ) + { + TileMultipart.addPart( world, pos, part ); + world.playSoundEffect( pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, blk.stepSound.getPlaceSound(), (blk.stepSound.getVolume() + 1.0F) / 2.0F, + blk.stepSound.getPitch() * 0.8F ); + if ( !player.capabilities.isCreativeMode ) + { + held.stackSize--; + if ( held.stackSize == 0 ) + { + player.inventory.mainInventory[player.inventory.currentItem] = null; + MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held ) ); + } + } + } + else + { + player.swingItem(); + try + { + PacketDispatcher.sendPacketToServer( (new PacketMultiPart()).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + return true; + } + + /** + * Because vanilla is weird. + */ + private static boolean ignoreActivate(Block block) + { + if ( block instanceof BlockFence ) + return true; + return false; + } +} diff --git a/fmp/PartRegistry.java b/fmp/PartRegistry.java new file mode 100644 index 00000000..7e4f450f --- /dev/null +++ b/fmp/PartRegistry.java @@ -0,0 +1,78 @@ +package appeng.fmp; + +import net.minecraft.block.Block; +import appeng.block.AEBaseBlock; +import appeng.block.misc.BlockQuartzTorch; +import appeng.block.networking.BlockCableBus; +import appeng.core.Api; +import codechicken.multipart.TMultiPart; + +public enum PartRegistry +{ + QuartzTorchPart("ae2_torch", BlockQuartzTorch.class, QuartzTorchPart.class), CableBusPart("ae2_cablebus", BlockCableBus.class, CableBusPart.class); + + final private String name; + final private Class blk; + final private Class part; + + public String getName() + { + return name; + } + + private PartRegistry(String name, Class blk, Class part) { + this.name = name; + this.blk = blk; + this.part = part; + } + + public TMultiPart construct(int meta) + { + try + { + if ( this == CableBusPart ) + return (TMultiPart) Api.instance.partHelper.getCombinedInstance( part.getName() ).newInstance(); + else + return part.getConstructor( int.class ).newInstance( meta ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } + + public static String getPartName(TMultiPart part) + { + Class c = part.getClass(); + for (PartRegistry pr : values()) + { + if ( pr.equals( c ) ) + return pr.getName(); + } + throw new RuntimeException( "Invalid PartName" ); + } + + public static TMultiPart getPartByBlock(Block block, int meta) + { + for (PartRegistry pr : values()) + { + if ( pr.blk.isInstance( block ) ) + { + return pr.construct( meta ); + } + } + return null; + } + + public static boolean isPart(Block block) + { + for (PartRegistry pr : values()) + { + if ( pr.blk.isInstance( block ) ) + { + return true; + } + } + return false; + } +} diff --git a/fmp/QuartzTorchPart.java b/fmp/QuartzTorchPart.java new file mode 100644 index 00000000..eb72c39f --- /dev/null +++ b/fmp/QuartzTorchPart.java @@ -0,0 +1,81 @@ +package appeng.fmp; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Cuboid6; +import codechicken.multipart.IRandomDisplayTick; +import codechicken.multipart.minecraft.McBlockPart; +import codechicken.multipart.minecraft.McSidedMetaPart; + +public class QuartzTorchPart extends McSidedMetaPart implements IRandomDisplayTick +{ + + public QuartzTorchPart() { + this( ForgeDirection.DOWN.ordinal() ); + } + + public QuartzTorchPart(int meta) { + super( meta ); + } + + @Override + public boolean doesTick() + { + return false; + } + + @Override + public Block getBlock() + { + return AEApi.instance().blocks().blockQuartzTorch.block(); + } + + @Override + public String getType() + { + return PartRegistry.QuartzTorchPart.getName(); + } + + @Override + public Cuboid6 getBounds() + { + return getBounds( meta ); + } + + public Cuboid6 getBounds(int meta) + { + ForgeDirection up = ForgeDirection.getOrientation( meta ); + double xOff = -0.3 * up.offsetX; + double yOff = -0.3 * up.offsetY; + double zOff = -0.3 * up.offsetZ; + return new Cuboid6( xOff + 0.3, yOff + 0.3, zOff + 0.3, xOff + 0.7, yOff + 0.7, zOff + 0.7 ); + } + + @Override + public int sideForMeta(int meta) + { + return ForgeDirection.getOrientation( meta ).getOpposite().ordinal(); + } + + public static McBlockPart placement(World world, BlockCoord pos, int side) + { + pos = pos.copy().offset( side ); + if ( !world.isBlockSolidOnSide( pos.x, pos.y, pos.z, ForgeDirection.getOrientation( side ) ) ) + { + return null; + } + + return new QuartzTorchPart( side ); + } + + @Override + public void randomDisplayTick(Random r) + { + getBlock().randomDisplayTick( world(), x(), y(), z(), r ); + } +} \ No newline at end of file diff --git a/helpers/AEMultiTile.java b/helpers/AEMultiTile.java new file mode 100644 index 00000000..bef994bd --- /dev/null +++ b/helpers/AEMultiTile.java @@ -0,0 +1,9 @@ +package appeng.helpers; + +import appeng.api.networking.IGridHost; +import appeng.api.parts.IPartHost; + +public interface AEMultiTile extends IGridHost, IPartHost +{ + +} diff --git a/helpers/AENoHandler.java b/helpers/AENoHandler.java new file mode 100644 index 00000000..714f0bf9 --- /dev/null +++ b/helpers/AENoHandler.java @@ -0,0 +1,8 @@ +package appeng.helpers; + +public class AENoHandler extends Exception +{ + + private static final long serialVersionUID = 7995805326136526631L; + +} diff --git a/helpers/AETrading.java b/helpers/AETrading.java new file mode 100644 index 00000000..00bff3a9 --- /dev/null +++ b/helpers/AETrading.java @@ -0,0 +1,85 @@ +package appeng.helpers; + +import java.util.Random; + +import net.minecraft.entity.passive.EntityVillager; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.village.MerchantRecipe; +import net.minecraft.village.MerchantRecipeList; +import appeng.api.AEApi; +import cpw.mods.fml.common.registry.VillagerRegistry.IVillageTradeHandler; + +public class AETrading implements IVillageTradeHandler +{ + + private void addToList(MerchantRecipeList l, ItemStack a, ItemStack b) + { + if ( a.stackSize < 1 ) + a.stackSize = 1; + if ( b.stackSize < 1 ) + b.stackSize = 1; + + if ( a.stackSize > a.getMaxStackSize() ) + a.stackSize = a.getMaxStackSize(); + if ( b.stackSize > b.getMaxStackSize() ) + b.stackSize = b.getMaxStackSize(); + + l.add( new MerchantRecipe( a, b ) ); + } + + private void addTrade(MerchantRecipeList list, ItemStack a, ItemStack b, Random rand, int convertion_Variance) + { + // Sell + ItemStack From = a.copy(); + ItemStack To = b.copy(); + + From.stackSize = 1 + (Math.abs( rand.nextInt() ) % (1 + convertion_Variance)); + To.stackSize = 1; + + addToList( list, From, To ); + } + + private void addMerchent(MerchantRecipeList list, ItemStack item, int emera, Random rand, int greed) + { + // Sell + ItemStack From = item.copy(); + ItemStack To = new ItemStack( Item.emerald ); + + int multiplier = (Math.abs( rand.nextInt() ) % 6); + emera += (Math.abs( rand.nextInt() ) % greed) - multiplier; + int mood = rand.nextInt() % 2; + + From.stackSize = multiplier + mood; + To.stackSize = multiplier * emera - mood; + + if ( To.stackSize < 0 ) + { + From.stackSize -= To.stackSize; + To.stackSize -= To.stackSize; + } + + addToList( list, From, To ); + + // Buy + ItemStack reverseTo = From.copy(); + ItemStack reverseFrom = To.copy(); + + reverseFrom.stackSize = (int) (reverseFrom.stackSize * (rand.nextFloat() * 3.0f + 1.0f)); + reverseTo.stackSize = reverseTo.stackSize; + + addToList( list, reverseFrom, reverseTo ); + } + + @Override + public void manipulateTradesForVillager(EntityVillager villager, MerchantRecipeList recipeList, Random random) + { + addMerchent( recipeList, AEApi.instance().materials().materialSilicon.stack( 1 ), 1, random, 1 ); + addMerchent( recipeList, AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), 2, random, 3 ); + addMerchent( recipeList, AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ), 1, random, 2 ); + + addTrade( recipeList, AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), random, 1 ); + } + +} diff --git a/helpers/CBIterator.java b/helpers/CBIterator.java new file mode 100644 index 00000000..9d626543 --- /dev/null +++ b/helpers/CBIterator.java @@ -0,0 +1,56 @@ +package appeng.helpers; + +import java.util.Iterator; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.parts.CableBusContainer; + +public class CBIterator implements Iterator +{ + + int side = 0; + CableBusContainer container; + + public CBIterator(CableBusContainer cableBusContainer) { + container = cableBusContainer; + } + + private void scan() + { + while (container.getPart( ForgeDirection.getOrientation( side ) ) == null) + { + side++; + if ( side > 6 ) + return; + } + } + + @Override + public boolean hasNext() + { + scan(); + if ( side <= 6 ) + return true; + return false; + } + + @Override + public IPart next() + { + scan(); + if ( side <= 6 ) + { + side++; + return container.getPart( ForgeDirection.getOrientation( side ) ); + } + return null; + } + + @Override + public void remove() + { + container.removePart( ForgeDirection.getOrientation( side ) ); + } + +} diff --git a/helpers/DispenserBehaviorTinyTNT.java b/helpers/DispenserBehaviorTinyTNT.java new file mode 100644 index 00000000..04408660 --- /dev/null +++ b/helpers/DispenserBehaviorTinyTNT.java @@ -0,0 +1,30 @@ +package appeng.helpers; + +import net.minecraft.block.BlockDispenser; +import net.minecraft.dispenser.BehaviorDefaultDispenseItem; +import net.minecraft.dispenser.IBlockSource; +import net.minecraft.entity.EntityLiving; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import appeng.entity.EntityTinyTNTPrimed; + +final public class DispenserBehaviorTinyTNT extends BehaviorDefaultDispenseItem +{ + + @Override + protected ItemStack dispenseStack(IBlockSource dispenser, ItemStack dispensedItem) + { + EnumFacing enumfacing = BlockDispenser.getFacing( dispenser.getBlockMetadata() ); + World world = dispenser.getWorld(); + int i = dispenser.getXInt() + enumfacing.getFrontOffsetX(); + int j = dispenser.getYInt() + enumfacing.getFrontOffsetY(); + int k = dispenser.getZInt() + enumfacing.getFrontOffsetZ(); + EntityTinyTNTPrimed entitytntprimed = new EntityTinyTNTPrimed( world, (double) ((float) i + 0.5F), (double) ((float) j + 0.5F), + (double) ((float) k + 0.5F), (EntityLiving) null ); + world.spawnEntityInWorld( entitytntprimed ); + --dispensedItem.stackSize; + return dispensedItem; + } + +} diff --git a/helpers/ICustomCollision.java b/helpers/ICustomCollision.java new file mode 100644 index 00000000..9ba2984f --- /dev/null +++ b/helpers/ICustomCollision.java @@ -0,0 +1,16 @@ +package appeng.helpers; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; + +public interface ICustomCollision +{ + + Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z); + + void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e); + +} diff --git a/helpers/ISharedTagCompoundCache.java b/helpers/ISharedTagCompoundCache.java new file mode 100644 index 00000000..cb53897d --- /dev/null +++ b/helpers/ISharedTagCompoundCache.java @@ -0,0 +1,23 @@ +package appeng.helpers; + +import net.minecraft.item.ItemStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.util.item.AEItemStack; + +public interface ISharedTagCompoundCache +{ + + final class CacheIAEItemStack + { + + ItemStack src; + AEItemStack stack; + }; + + CacheIAEItemStack[] itemStackCache = new CacheIAEItemStack[0]; + + void checkCacheSetup(int size); + + IAEItemStack getItem(int x, ItemStack is); + +} diff --git a/helpers/InventoryAction.java b/helpers/InventoryAction.java new file mode 100644 index 00000000..dfc7ea47 --- /dev/null +++ b/helpers/InventoryAction.java @@ -0,0 +1,10 @@ +package appeng.helpers; + +public enum InventoryAction +{ + // standard vanilla mechanics. + PICKUP_OR_SETDOWN, SPLIT_OR_PLACESINGLE, CREATIVE_DUPLICATE, SHIFT_CLICK, + + // extra... + MOVE_REGION +} diff --git a/helpers/LocationRotation.java b/helpers/LocationRotation.java new file mode 100644 index 00000000..650ce224 --- /dev/null +++ b/helpers/LocationRotation.java @@ -0,0 +1,48 @@ +package appeng.helpers; + +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.IOrientable; + +public class LocationRotation implements IOrientable +{ + + final IBlockAccess w; + final int x; + final int y; + final int z; + + public LocationRotation(IBlockAccess world, int x, int y, int z) { + w = world; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void setOrientation(ForgeDirection Forward, ForgeDirection Up) + { + + } + + @Override + public ForgeDirection getUp() + { + int num = Math.abs( x + y + z ) % 6; + return ForgeDirection.getOrientation( num ); + } + + @Override + public ForgeDirection getForward() + { + if ( getUp().offsetY == 0 ) + return ForgeDirection.UP; + return ForgeDirection.SOUTH; + } + + @Override + public boolean canBeRotated() + { + return true; + } +} diff --git a/helpers/MetaRotation.java b/helpers/MetaRotation.java new file mode 100644 index 00000000..14849952 --- /dev/null +++ b/helpers/MetaRotation.java @@ -0,0 +1,51 @@ +package appeng.helpers; + +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.IOrientable; + +public class MetaRotation implements IOrientable +{ + + final IBlockAccess w; + final int x; + final int y; + final int z; + + public MetaRotation(IBlockAccess world, int x, int y, int z) { + w = world; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public void setOrientation(ForgeDirection Forward, ForgeDirection Up) + { + if ( w instanceof World ) + ((World) w).setBlockMetadataWithNotify( x, y, z, Up.ordinal(), 1 + 2 ); + else + throw new RuntimeException( w.getClass().getName() + " recieved, exptected World" ); + } + + @Override + public ForgeDirection getUp() + { + return ForgeDirection.getOrientation( w.getBlockMetadata( x, y, z ) ); + } + + @Override + public ForgeDirection getForward() + { + if ( getUp().offsetY == 0 ) + return ForgeDirection.UP; + return ForgeDirection.SOUTH; + } + + @Override + public boolean canBeRotated() + { + return true; + } +} diff --git a/helpers/PartPlacement.java b/helpers/PartPlacement.java new file mode 100644 index 00000000..e1a45f0a --- /dev/null +++ b/helpers/PartPlacement.java @@ -0,0 +1,311 @@ +package appeng.helpers; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.StepSound; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; +import appeng.api.AEApi; +import appeng.api.parts.IFacadePart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartItem; +import appeng.api.parts.SelectedPart; +import appeng.core.AppEng; +import appeng.core.sync.packets.PacketPartPlacement; +import appeng.facade.IFacadeItem; +import appeng.integration.abstraction.IBC; +import appeng.integration.abstraction.IFMP; +import appeng.util.LookDirection; +import appeng.util.Platform; +import cpw.mods.fml.common.network.PacketDispatcher; + +public class PartPlacement +{ + + private ThreadLocal placing = new ThreadLocal(); + + @ForgeSubscribe + public void playerInteract(PlayerInteractEvent event) + { + if ( event.action == Action.RIGHT_CLICK_BLOCK && event.entityPlayer.worldObj.isRemote ) + { + if ( placing.get() != null ) + return; + + placing.set( event ); + + ItemStack held = event.entityPlayer.getHeldItem(); + if ( place( held, event.x, event.y, event.z, event.face, event.entityPlayer, event.entityPlayer.worldObj, PlaceType.INTERACT_FIRST_PASS, 0 ) ) + event.setCanceled( true ); + + placing.set( null ); + } + } + + public enum PlaceType + { + PLACE_ITEM, INTERACT_FIRST_PASS, INTERACT_SECOND_PASS + }; + + public static boolean place(ItemStack held, int x, int y, int z, int face, EntityPlayer player, World world, PlaceType pass, int depth) + { + if ( depth > 3 ) + return false; + + ForgeDirection side = ForgeDirection.getOrientation( face ); + + if ( held == null ) + return false; + + if ( Platform.isWrench( player, held, x, y, z ) ) + { + int block = world.getBlockId( x, y, z ); + TileEntity tile = world.getBlockTileEntity( x, y, z ); + IPartHost host = null; + + if ( tile instanceof IPartHost ) + host = (IPartHost) tile; + + if ( host != null ) + { + if ( !world.isRemote ) + { + LookDirection dir = Platform.getPlayerRay( player ); + MovingObjectPosition mop = Block.blocksList[block].collisionRayTrace( world, x, y, z, dir.a, dir.b ); + if ( mop != null ) + { + List is = new LinkedList(); + SelectedPart sp = host.selectPart( mop.hitVec.addVector( -mop.blockX, -mop.blockY, -mop.blockZ ) ); + + if ( sp.part != null ) + { + is.add( sp.part.getItemStack( true ) ); + sp.part.getDrops( is, true ); + host.removePart( sp.side ); + } + + if ( sp.facade != null ) + { + is.add( sp.facade.getItemStack() ); + host.getFacadeContainer().removeFacade( host, sp.side ); + } + + if ( is != null && !is.isEmpty() ) + { + Platform.spawnDrops( world, x, y, z, is ); + } + } + } + else + { + player.swingItem(); + try + { + PacketDispatcher.sendPacketToServer( (new PacketPartPlacement( x, y, z, face )).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + return false; + } + + TileEntity tile = world.getBlockTileEntity( x, y, z ); + IPartHost host = null; + + if ( tile instanceof IPartHost ) + host = (IPartHost) tile; + + IFacadePart fp = isFacade( held, side ); + if ( fp != null ) + { + if ( host != null ) + { + if ( !world.isRemote ) + { + if ( host.getPart( ForgeDirection.UNKNOWN ) == null ) + return false; + + if ( host.getFacadeContainer().addFacade( fp ) ) + { + host.markForUpdate(); + if ( !player.capabilities.isCreativeMode ) + { + held.stackSize--; + if ( held.stackSize == 0 ) + { + player.inventory.mainInventory[player.inventory.currentItem] = null; + MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held ) ); + } + } + return true; + } + } + else + { + player.swingItem(); + try + { + PacketDispatcher.sendPacketToServer( (new PacketPartPlacement( x, y, z, face )).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + return false; + } + + if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( "FMP" ) ) + host = ((IFMP) AppEng.instance.getIntegration( "FMP" )).getOrCreateHost( tile ); + + if ( !(held.getItem() instanceof IPartItem) ) + return false; + + int te_x = x; + int te_y = y; + int te_z = z; + + if ( host == null && pass == PlaceType.PLACE_ITEM ) + { + ItemStack is = AEApi.instance().blocks().blockMultiPart.stack( 1 ); + ItemBlock ib = (ItemBlock) is.getItem(); + ForgeDirection offset = ForgeDirection.UNKNOWN; + + int blkID = world.getBlockId( x, y, z ); + if ( blkID != 0 && !Block.blocksList[blkID].isBlockReplaceable( world, x, y, z ) ) + { + offset = side; + if ( Platform.isServer() ) + side = side.getOpposite(); + } + + te_x = x + offset.offsetX; + te_y = y + offset.offsetY; + te_z = z + offset.offsetZ; + + tile = world.getBlockTileEntity( te_x, te_y, te_z ); + if ( tile instanceof IPartHost ) + host = (IPartHost) tile; + + if ( host == null && tile != null && AppEng.instance.isIntegrationEnabled( "FMP" ) ) + host = ((IFMP) AppEng.instance.getIntegration( "FMP" )).getOrCreateHost( tile ); + + if ( host == null && AEApi.instance().blocks().blockMultiPart.block().canPlaceBlockAt( world, te_x, te_y, te_z ) + && ib.placeBlockAt( is, player, world, te_x, te_y, te_z, side.ordinal(), 0.5f, 0.5f, 0.5f, 0 ) ) + { + if ( !world.isRemote ) + { + tile = world.getBlockTileEntity( te_x, te_y, te_z ); + + if ( tile instanceof IPartHost ) + host = (IPartHost) tile; + + pass = PlaceType.INTERACT_SECOND_PASS; + } + else + { + player.swingItem(); + try + { + PacketDispatcher.sendPacketToServer( (new PacketPartPlacement( x, y, z, face )).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + return true; + } + } + } + + if ( host == null ) + return false; + + if ( !host.canAddPart( held, side ) ) + { + if ( pass == PlaceType.INTERACT_FIRST_PASS || pass == PlaceType.PLACE_ITEM ) + { + ForgeDirection offset = side; + + te_x = x + offset.offsetX; + te_y = y + offset.offsetY; + te_z = z + offset.offsetZ; + + int blkID = world.getBlockId( te_x, te_y, te_z ); + tile = world.getBlockTileEntity( te_x, te_y, te_z ); + + if ( tile != null && AppEng.instance.isIntegrationEnabled( "FMP" ) ) + host = ((IFMP) AppEng.instance.getIntegration( "FMP" )).getOrCreateHost( tile ); + + if ( (blkID == 0 || Block.blocksList[blkID].isBlockReplaceable( world, te_x, te_y, te_z ) || host != null) && offset != ForgeDirection.UNKNOWN ) + return place( held, te_x, te_y, te_z, side.getOpposite().ordinal(), player, world, pass == PlaceType.INTERACT_FIRST_PASS ? PlaceType.INTERACT_SECOND_PASS + : PlaceType.PLACE_ITEM, depth + 1 ); + } + return false; + } + + if ( !world.isRemote ) + { + if ( host.addPart( held, side ) != null ) + { + StepSound ss = AEApi.instance().blocks().blockMultiPart.block().stepSound; + world.playSoundEffect( 0.5 + x, 0.5 + y, 0.5 + z, ss.getPlaceSound(), (ss.getVolume() + 1.0F) / 2.0F, ss.getPitch() * 0.8F ); + + if ( !player.capabilities.isCreativeMode ) + { + held.stackSize--; + if ( held.stackSize == 0 ) + { + player.inventory.mainInventory[player.inventory.currentItem] = null; + MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held ) ); + } + } + } + } + else + { + player.swingItem(); + try + { + PacketDispatcher.sendPacketToServer( (new PacketPartPlacement( x, y, z, face )).getPacket() ); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + return true; + } + + private static IFacadePart isFacade(ItemStack held, ForgeDirection side) + { + if ( held.getItem() instanceof IFacadeItem ) + return ((IFacadeItem) held.getItem()).createPartFromItemStack( held, side ); + if ( AppEng.instance.isIntegrationEnabled( "BC" ) ) + { + IBC bc = (IBC) AppEng.instance.getIntegration( "BC" ); + if ( bc.isFacade( held ) ) + return bc.createFacadePart( held, side ); + } + return null; + } + +} \ No newline at end of file diff --git a/helpers/QuartzWorldGen.java b/helpers/QuartzWorldGen.java new file mode 100644 index 00000000..e1fe1b3d --- /dev/null +++ b/helpers/QuartzWorldGen.java @@ -0,0 +1,54 @@ +package appeng.helpers; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.feature.WorldGenMinable; +import appeng.api.AEApi; +import appeng.core.Configuration; +import cpw.mods.fml.common.IWorldGenerator; + +final public class QuartzWorldGen implements IWorldGenerator +{ + + final WorldGenMinable oreNormal; + final WorldGenMinable oreCharged; + + public QuartzWorldGen() { + ItemStack normal = AEApi.instance().blocks().blockQuartzOre.stack( 1 ); + ItemStack charged = AEApi.instance().blocks().blockQuartzOreCharged.stack( 1 ); + + if ( normal == null || charged == null ) + { + oreNormal = new WorldGenMinable( normal.itemID, normal.getItemDamage(), Configuration.instance.oresPerCluster, Block.stone.blockID ); + oreCharged = new WorldGenMinable( normal.itemID, normal.getItemDamage(), Configuration.instance.oresPerCluster, Block.stone.blockID ); + } + else + oreNormal = oreCharged = null; + }; + + @Override + public void generate(Random r, int chunkX, int chunkZ, World w, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) + { + int sealevel = w.provider.getAverageGroundLevel() + 1; + + if ( oreNormal == null || oreCharged == null ) + return; + + double oreDepthMultiplier = 15 * sealevel / 64; + int scale = (int) Math.round( r.nextGaussian() * Math.sqrt( oreDepthMultiplier ) + oreDepthMultiplier ); + + for (int x = 0; x < (r.nextBoolean() ? scale * 2 : scale) / 2; ++x) + { + WorldGenMinable whichOre = r.nextFloat() > 0.92 ? oreCharged : oreNormal; + int a = chunkX * 16 + r.nextInt( 22 ); + int b = r.nextInt( 40 * sealevel / 64 ) + r.nextInt( 22 * sealevel / 64 ) + 12 * sealevel / 64; + int c = chunkZ * 16 + r.nextInt( 22 ); + whichOre.generate( w, r, a, b, c ); + } + + } +} diff --git a/helpers/TickHandler.java b/helpers/TickHandler.java new file mode 100644 index 00000000..8e0eb9c6 --- /dev/null +++ b/helpers/TickHandler.java @@ -0,0 +1,123 @@ +package appeng.helpers; + +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.WorldEvent; +import appeng.api.networking.IGridNode; +import appeng.me.Grid; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; +import cpw.mods.fml.common.ITickHandler; +import cpw.mods.fml.common.TickType; + +public class TickHandler implements ITickHandler +{ + + class HandlerRep + { + + public Queue tiles = new LinkedList(); + + public List networks = new LinkedList(); + + public void clear() + { + tiles = new LinkedList(); + networks = new LinkedList(); + } + + }; + + final public static TickHandler instance = new TickHandler(); + + final private HandlerRep server = new HandlerRep(); + final private HandlerRep client = new HandlerRep(); + + HandlerRep getRepo() + { + if ( Platform.isServer() ) + return server; + return client; + } + + public void addInit(AEBaseTile tile) + { + getRepo().tiles.add( tile ); + } + + public void addNetwork(Grid grid) + { + if ( Platform.isServer() ) + getRepo().networks.add( grid ); + } + + public void removeNetwork(Grid grid) + { + if ( Platform.isServer() ) + getRepo().networks.remove( grid ); + } + + public Iterable getGridList() + { + return getRepo().networks; + } + + public void shutdown() + { + getRepo().clear(); + } + + @ForgeSubscribe + public void unloadWorld(WorldEvent.Unload ev) + { + if ( Platform.isServer() ) + { + for (Grid g : getRepo().networks) + { + for (IGridNode n : g.getNodes()) + { + if ( n.getWorld() == ev.world ) + n.destroy(); + } + } + } + } + + @Override + public void tickStart(EnumSet type, Object... tickData) + { + + } + + @Override + public void tickEnd(EnumSet type, Object... tickData) + { + HandlerRep repo = getRepo(); + while (!repo.tiles.isEmpty()) + { + AEBaseTile bt = repo.tiles.poll(); + bt.onReady(); + } + + for (Grid g : getRepo().networks) + { + g.update(); + } + } + + @Override + public EnumSet ticks() + { + return EnumSet.of( TickType.WORLD ); + } + + @Override + public String getLabel() + { + return "AE-TickHandler"; + } +} diff --git a/integration/IIntegrationModule.java b/integration/IIntegrationModule.java new file mode 100644 index 00000000..a627a947 --- /dev/null +++ b/integration/IIntegrationModule.java @@ -0,0 +1,10 @@ +package appeng.integration; + +public interface IIntegrationModule +{ + + void Init() throws Throwable; + + void PostInit() throws Throwable; + +} diff --git a/integration/IntegrationNode.java b/integration/IntegrationNode.java new file mode 100644 index 00000000..75d3d268 --- /dev/null +++ b/integration/IntegrationNode.java @@ -0,0 +1,107 @@ +package appeng.integration; + +import java.lang.reflect.Field; + +import appeng.api.exceptions.ModNotInstalled; +import appeng.core.AELog; +import appeng.core.Configuration; +import cpw.mods.fml.common.Loader; + +public class IntegrationNode +{ + + IntegrationStage state = IntegrationStage.PREINIT; + IntegrationStage failedStage = IntegrationStage.PREINIT; + Throwable exception = null; + + String displayName; + String modID; + + String shortName; + String name = null; + Class classValue = null; + Object instance; + IIntegrationModule mod = null; + + public IntegrationNode(String dspname, String _modID, String sName, String n) { + displayName = dspname; + shortName = sName; + modID = _modID; + name = n; + } + + void Call(IntegrationStage stage) + { + if ( isActive() ) + { + try + { + switch (stage) + { + case PREINIT: + + boolean enabled = modID == null || Loader.isModLoaded( modID ); + + Configuration.instance + .addCustomCategoryComment( + "ModIntegration", + "Valid Values are 'AUTO', 'ON', or 'OFF' - defaults to 'AUTO' ; Suggested that you leave this alone unless your experiencing an issue, or wish to disable the integration for a reason." ); + String Mode = Configuration.instance.get( "ModIntegration", displayName.replace( " ", "" ), "AUTO" ) + .getString(); + + if ( Mode.toUpperCase().equals( "ON" ) ) + enabled = true; + if ( Mode.toUpperCase().equals( "OFF" ) ) + enabled = false; + + if ( enabled ) + { + classValue = getClass().getClassLoader().loadClass( name ); + mod = (IIntegrationModule) classValue.getConstructor().newInstance(); + Field f = classValue.getField( "instance" ); + f.set( classValue, instance = mod ); + } + else + throw new ModNotInstalled( modID ); + + break; + case INIT: + mod.Init(); + break; + case POSTINIT: + mod.PostInit(); + break; + case FAILED: + default: + break; + } + } + catch (Throwable t) + { + failedStage = stage; + exception = t; + state = IntegrationStage.FAILED; + } + } + + if ( stage == IntegrationStage.POSTINIT ) + { + if ( state == IntegrationStage.FAILED ) + { + AELog.info( displayName + " - Integration Disabled" ); + if ( !(exception instanceof ModNotInstalled) ) + exception.printStackTrace(); + } + else + { + AELog.info( displayName + " - Integration Enable" ); + } + } + } + + public boolean isActive() + { + return state != IntegrationStage.FAILED; + } + +} diff --git a/integration/IntegrationRegistry.java b/integration/IntegrationRegistry.java new file mode 100644 index 00000000..1a936887 --- /dev/null +++ b/integration/IntegrationRegistry.java @@ -0,0 +1,135 @@ +package appeng.integration; + +import java.util.LinkedList; + +import appeng.util.Platform; + +public class IntegrationRegistry +{ + + public static IntegrationRegistry instance = null; + + private LinkedList modules = new LinkedList(); + + public void loadIntegration(IntegrationSide side, String dspname, String modID, String name) + { + if ( side == IntegrationSide.CLIENT && Platform.isServer() ) + return; + + if ( side == IntegrationSide.SERVER && Platform.isClient() ) + return; + + modules.add( new IntegrationNode( dspname, modID, name, "appeng.integration.modules." + name ) ); + } + + private void die() + { + throw new RuntimeException( "Invalid Mod Integration Registry config, please check parameters." ); + } + + public IntegrationRegistry(Object[] name) { + instance = this; + + int stage = 0; + + IntegrationSide side = null; + String dspName = null; + String modID = null; + for (Object n : name) + { + stage++; + if ( stage == 1 ) + { + if ( n instanceof IntegrationSide ) + side = (IntegrationSide) n; + else + die(); + } + else if ( stage == 2 ) + { + if ( n instanceof String ) + dspName = (String) n; + else + die(); + } + else if ( stage == 3 ) + { + if ( n instanceof String || n == null ) + modID = (String) n; + else + die(); + } + else + { + if ( n instanceof String ) + { + loadIntegration( side, dspName, modID, (String) n ); + side = null; + dspName = null; + modID = null; + stage = 0; + } + else + die(); + } + } + + if ( dspName != null || modID != null ) + die(); + } + + public void init() + { + for (IntegrationNode node : modules) + node.Call( IntegrationStage.PREINIT ); + + for (IntegrationNode node : modules) + node.Call( IntegrationStage.INIT ); + } + + public void postinit() + { + for (IntegrationNode node : modules) + node.Call( IntegrationStage.POSTINIT ); + } + + public String getStatus() + { + String out = null; + + for (IntegrationNode node : modules) + { + String str = node.shortName + ":" + (node.state == IntegrationStage.FAILED ? "OFF" : "ON"); + + if ( out == null ) + out = str; + else + out += ", " + str; + } + + return out; + } + + public boolean isEnabled(String name) + { + for (IntegrationNode node : modules) + { + if ( node.shortName.equals( name ) ) + return node.isActive(); + } + throw new RuntimeException( "invalid integration" ); + } + + public Object getInstance(String name) + { + for (IntegrationNode node : modules) + { + if ( node.shortName.equals( name ) && node.isActive() ) + { + return node.instance; + } + } + throw new RuntimeException( "invalid integration" ); + } + +} diff --git a/integration/IntegrationSide.java b/integration/IntegrationSide.java new file mode 100644 index 00000000..e691ec20 --- /dev/null +++ b/integration/IntegrationSide.java @@ -0,0 +1,6 @@ +package appeng.integration; + +public enum IntegrationSide +{ + CLIENT, SERVER, BOTH +} diff --git a/integration/IntegrationStage.java b/integration/IntegrationStage.java new file mode 100644 index 00000000..38f0dd66 --- /dev/null +++ b/integration/IntegrationStage.java @@ -0,0 +1,9 @@ +package appeng.integration; + +public enum IntegrationStage +{ + + PREINIT, INIT, POSTINIT, + + FAILED +} diff --git a/integration/abstraction/IBC.java b/integration/abstraction/IBC.java new file mode 100644 index 00000000..e2d7f3fd --- /dev/null +++ b/integration/abstraction/IBC.java @@ -0,0 +1,44 @@ +package appeng.integration.abstraction; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IFacadePart; + +public interface IBC +{ + + boolean isWrench(Item eq); + + boolean canWrench(Item i, EntityPlayer p, int x, int y, int z); + + void wrenchUsed(Item i, EntityPlayer p, int x, int y, int z); + + boolean canAddItemsToPipe(TileEntity te, ItemStack is, ForgeDirection dir); + + boolean addItemsToPipe(TileEntity te, ItemStack is, ForgeDirection dir); + + boolean isFacade(ItemStack is); + + boolean isPipe(TileEntity te, ForgeDirection dir); + + void addFacade(ItemStack item); + + void registerPowerP2P(); + + void registerItemP2P(); + + void registerLiquidsP2P(); + + IFacadePart createFacadePart(int[] ids, ForgeDirection side); + + IFacadePart createFacadePart(ItemStack held, ForgeDirection side); + + ItemStack getTextureForFacade(ItemStack facade); + + Icon getFacadeTexture(); + +} diff --git a/integration/abstraction/IBS.java b/integration/abstraction/IBS.java new file mode 100644 index 00000000..6e7e14ae --- /dev/null +++ b/integration/abstraction/IBS.java @@ -0,0 +1,13 @@ +package appeng.integration.abstraction; + +import net.minecraftforge.common.ForgeDirection; +import appeng.util.InventoryAdaptor; + +public interface IBS +{ + + boolean isStorageCrate(Object te); + + InventoryAdaptor getAdaptor(Object te, ForgeDirection d); + +} diff --git a/integration/abstraction/IFMP.java b/integration/abstraction/IFMP.java new file mode 100644 index 00000000..19a69d6e --- /dev/null +++ b/integration/abstraction/IFMP.java @@ -0,0 +1,16 @@ +package appeng.integration.abstraction; + +import net.minecraft.tileentity.TileEntity; +import appeng.api.parts.IPartHost; +import appeng.parts.CableBusContainer; + +public interface IFMP +{ + + IPartHost getOrCreateHost(TileEntity tile); + + CableBusContainer getCableContainer(TileEntity te); + + void registerPassThru(Class layerInterface); + +} diff --git a/integration/abstraction/IFZ.java b/integration/abstraction/IFZ.java new file mode 100644 index 00000000..275764ca --- /dev/null +++ b/integration/abstraction/IFZ.java @@ -0,0 +1,24 @@ +package appeng.integration.abstraction; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import appeng.api.storage.IMEInventory; + +public interface IFZ +{ + + ItemStack barrelGetItem(TileEntity te); + + int barrelGetMaxItemCount(TileEntity te); + + int barrelGetItemCount(TileEntity te); + + void setItemType(TileEntity te, ItemStack input); + + void barrelSetCount(TileEntity te, int max); + + IMEInventory getFactorizationBarrel(TileEntity te); + + boolean isBarrel(TileEntity te); + +} diff --git a/integration/abstraction/IForestry.java b/integration/abstraction/IForestry.java new file mode 100644 index 00000000..86b95b14 --- /dev/null +++ b/integration/abstraction/IForestry.java @@ -0,0 +1,10 @@ +package appeng.integration.abstraction; + +import appeng.api.features.IItemComparisionProvider; + +public interface IForestry +{ + + IItemComparisionProvider getGeneticsComparisonProvider(); + +} \ No newline at end of file diff --git a/integration/abstraction/IGT.java b/integration/abstraction/IGT.java new file mode 100644 index 00000000..76467369 --- /dev/null +++ b/integration/abstraction/IGT.java @@ -0,0 +1,13 @@ +package appeng.integration.abstraction; + +import net.minecraft.tileentity.TileEntity; +import appeng.api.storage.IMEInventory; + +public interface IGT +{ + + boolean isQuantumChest(TileEntity te); + + IMEInventory getQuantumChest(TileEntity te); + +} diff --git a/integration/abstraction/IIC2.java b/integration/abstraction/IIC2.java new file mode 100644 index 00000000..f2023009 --- /dev/null +++ b/integration/abstraction/IIC2.java @@ -0,0 +1,26 @@ +package appeng.integration.abstraction; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; + +public interface IIC2 +{ + + boolean canUse(ItemStack i, int powerusage); + + boolean use(ItemStack i, int powerusage, EntityPlayer p); + + int discharge(ItemStack i, int powerusage, int tier, boolean ignoreTransferLimit, boolean simulate); + + void addCompressorRecipe(ItemStack dustRecipe, ItemStack matQuartz); + + void addMaceratorRecipe(ItemStack itemStack, ItemStack matFlour); + + void addToEnergyNet(TileEntity appEngTile); + + void removeFromEnergyNet(TileEntity appEngTile); + + ItemStack getItem(String string); + +} diff --git a/integration/abstraction/IInvTweaks.java b/integration/abstraction/IInvTweaks.java new file mode 100644 index 00000000..6d83eea3 --- /dev/null +++ b/integration/abstraction/IInvTweaks.java @@ -0,0 +1,10 @@ +package appeng.integration.abstraction; + +import net.minecraft.item.ItemStack; + +public interface IInvTweaks +{ + + int compareItems(ItemStack i, ItemStack j); + +} diff --git a/integration/abstraction/ILP.java b/integration/abstraction/ILP.java new file mode 100644 index 00000000..45369504 --- /dev/null +++ b/integration/abstraction/ILP.java @@ -0,0 +1,30 @@ +package appeng.integration.abstraction; + +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import appeng.api.storage.IMEInventory; + +public interface ILP +{ + + List getCraftedItems(TileEntity te); + + List getProvidedItems(TileEntity te); + + boolean isRequestPipe(TileEntity te); + + List performRequest(TileEntity te, ItemStack wanted); + + IMEInventory getInv(TileEntity te); + + Object getGetPowerPipe(TileEntity te); + + boolean isPowerSource(TileEntity tt); + + boolean canUseEnergy(Object pp, int ceil, List providersToIgnore); + + boolean useEnergy(Object pp, int ceil, List providersToIgnore); + +} diff --git a/integration/abstraction/IMFR.java b/integration/abstraction/IMFR.java new file mode 100644 index 00000000..7f403d75 --- /dev/null +++ b/integration/abstraction/IMFR.java @@ -0,0 +1,13 @@ +package appeng.integration.abstraction; + +import net.minecraft.tileentity.TileEntity; +import appeng.api.storage.IMEInventory; + +public interface IMFR +{ + + IMEInventory getDSU(TileEntity te); + + boolean isDSU(TileEntity te); + +} diff --git a/integration/abstraction/IMekanism.java b/integration/abstraction/IMekanism.java new file mode 100644 index 00000000..cc9fb1f9 --- /dev/null +++ b/integration/abstraction/IMekanism.java @@ -0,0 +1,10 @@ +package appeng.integration.abstraction; + +import net.minecraft.item.ItemStack; + +public interface IMekanism +{ + + void addMaceratorRecipe(ItemStack in, ItemStack out); + +} diff --git a/integration/abstraction/ITE.java b/integration/abstraction/ITE.java new file mode 100644 index 00000000..379fcc1c --- /dev/null +++ b/integration/abstraction/ITE.java @@ -0,0 +1,12 @@ +package appeng.integration.abstraction; + +import net.minecraft.item.ItemStack; + +public interface ITE +{ + + void addPulverizerRecipe(int i, ItemStack blkQuartz, ItemStack blockDust); + + void addPulverizerRecipe(int i, ItemStack blkQuartzOre, ItemStack matQuartz, ItemStack matQuartzDust); + +} diff --git a/integration/abstraction/IUE.java b/integration/abstraction/IUE.java new file mode 100644 index 00000000..354f74b6 --- /dev/null +++ b/integration/abstraction/IUE.java @@ -0,0 +1,6 @@ +package appeng.integration.abstraction; + +public interface IUE +{ + +} \ No newline at end of file diff --git a/integration/modules/BC.java b/integration/modules/BC.java new file mode 100644 index 00000000..60a4cf32 --- /dev/null +++ b/integration/modules/BC.java @@ -0,0 +1,221 @@ +package appeng.integration.modules; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.config.TunnelType; +import appeng.api.features.IP2PTunnelRegistry; +import appeng.api.parts.IFacadePart; +import appeng.facade.FacadePart; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IBC; +import buildcraft.BuildCraftEnergy; +import buildcraft.BuildCraftTransport; +import buildcraft.api.tools.IToolWrench; +import buildcraft.api.transport.FacadeManager; +import buildcraft.api.transport.IPipeTile; +import buildcraft.api.transport.IPipeTile.PipeType; +import buildcraft.transport.ItemFacade; +import buildcraft.transport.PipeIconProvider; +import buildcraft.transport.TileGenericPipe; + +public class BC implements IIntegrationModule, IBC +{ + + public static BC instance; + + @Override + public void addFacade(ItemStack item) + { + // Myrathi : + // FMLInterModComms.sendMessage("BuildCraft|Transport", "add-facade", + // + "@" + ); + FacadeManager.addFacade( item ); + } + + @Override + public boolean isWrench(Item eq) + { + return eq instanceof IToolWrench; + } + + @Override + public boolean isPipe(TileEntity te, ForgeDirection dir) + { + if ( te instanceof IPipeTile ) + { + try + { + if ( te instanceof TileGenericPipe ) + if ( ((TileGenericPipe) te).hasPlug( dir.getOpposite() ) ) + return false; + } + catch (Exception err) + { + } + + return true; + } + + return false; + } + + @Override + public boolean canWrench(Item i, EntityPlayer p, int x, int y, int z) + { + return ((IToolWrench) i).canWrench( p, x, y, z ); + } + + @Override + public void wrenchUsed(Item i, EntityPlayer p, int x, int y, int z) + { + ((IToolWrench) i).wrenchUsed( p, x, y, z ); + } + + @Override + public boolean addItemsToPipe(TileEntity te, ItemStack is, ForgeDirection dir) + { + if ( is != null && te != null && te instanceof IPipeTile ) + { + IPipeTile pt = (IPipeTile) te; + if ( pt.getPipeType() == PipeType.ITEM ) + { + int amt = pt.injectItem( is, false, dir ); + if ( amt == is.stackSize ) + { + pt.injectItem( is, true, dir ); + return true; + } + } + } + + return false; + } + + @Override + public boolean isFacade(ItemStack is) + { + if ( is == null ) + return false; + return is.getItem() instanceof ItemFacade; + } + + @Override + public boolean canAddItemsToPipe(TileEntity te, ItemStack is, ForgeDirection dir) + { + + if ( is != null && te != null && te instanceof IPipeTile ) + { + IPipeTile pt = (IPipeTile) te; + if ( pt.getPipeType() == PipeType.ITEM ) + { + int amt = pt.injectItem( is, false, dir ); + if ( amt == is.stackSize ) + { + return true; + } + } + } + + return false; + } + + @Override + public void registerPowerP2P() + { + IP2PTunnelRegistry reg = AEApi.instance().registries().p2pTunnel(); + reg.addNewAttunement( new ItemStack( BuildCraftEnergy.engineBlock, 1, 0 ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftEnergy.engineBlock, 1, 1 ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftEnergy.engineBlock, 1, 2 ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerCobblestone ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerDiamond ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerGold ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerQuartz ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerStone ), TunnelType.BC_POWER ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipePowerWood ), TunnelType.BC_POWER ); + } + + @Override + public void registerItemP2P() + { + IP2PTunnelRegistry reg = AEApi.instance().registries().p2pTunnel(); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsWood ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsVoid ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsSandstone ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsQuartz ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsObsidian ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsIron ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsGold ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsEmerald ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsDiamond ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsStone ), TunnelType.ITEM ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeItemsCobblestone ), TunnelType.ITEM ); + } + + @Override + public void registerLiquidsP2P() + { + IP2PTunnelRegistry reg = AEApi.instance().registries().p2pTunnel(); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsCobblestone ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsEmerald ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsGold ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsIron ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsSandstone ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsStone ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsVoid ), TunnelType.FLUID ); + reg.addNewAttunement( new ItemStack( BuildCraftTransport.pipeFluidsWood ), TunnelType.FLUID ); + } + + @Override + public void Init() + { + + } + + @Override + public void PostInit() + { + registerPowerP2P(); + registerItemP2P(); + registerLiquidsP2P(); + } + + @Override + public IFacadePart createFacadePart(int[] ids, ForgeDirection side) + { + ItemStack fs = ItemFacade.getStack( ids[0], ids[1] ); + return new FacadePart( fs, side ); + } + + @Override + public IFacadePart createFacadePart(ItemStack fs, ForgeDirection side) + { + return new FacadePart( fs, side ); + } + + @Override + public ItemStack getTextureForFacade(ItemStack facade) + { + return new ItemStack( Block.blocksList[ItemFacade.getBlockId( facade )], 1, ItemFacade.getMetaData( facade ) ); + } + + @Override + public Icon getFacadeTexture() + { + try + { + return BuildCraftTransport.instance.pipeIconProvider.getIcon( PipeIconProvider.TYPE.PipeStructureCobblestone.ordinal() ); // Structure + } + catch (Throwable t) + { + } + return null; + // Pipe + } + +} diff --git a/integration/modules/BS.java b/integration/modules/BS.java new file mode 100644 index 00000000..85d88ebc --- /dev/null +++ b/integration/modules/BS.java @@ -0,0 +1,45 @@ +package appeng.integration.modules; + +import net.mcft.copy.betterstorage.api.ICrateStorage; +import net.minecraftforge.common.ForgeDirection; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IBS; +import appeng.integration.modules.helpers.BSCrateStorageAdaptor; +import appeng.util.InventoryAdaptor; + +public class BS implements IIntegrationModule, IBS +{ + + public static BS instance; + + @Override + public boolean isStorageCrate(Object te) + { + return te instanceof ICrateStorage; + } + + @Override + public InventoryAdaptor getAdaptor(Object te, ForgeDirection d) + { + if ( te instanceof ICrateStorage ) + { + return new BSCrateStorageAdaptor( te, d ); + } + return null; + } + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/FMP.java b/integration/modules/FMP.java new file mode 100644 index 00000000..8a5f8091 --- /dev/null +++ b/integration/modules/FMP.java @@ -0,0 +1,152 @@ +package appeng.integration.modules; + +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import appeng.api.AEApi; +import appeng.api.parts.IPartHost; +import appeng.core.AELog; +import appeng.fmp.CableBusPart; +import appeng.fmp.FMPEvent; +import appeng.fmp.PartRegistry; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IFMP; +import appeng.parts.CableBusContainer; +import appeng.util.Platform; +import codechicken.lib.vec.BlockCoord; +import codechicken.microblock.BlockMicroMaterial; +import codechicken.multipart.MultiPartRegistry; +import codechicken.multipart.MultiPartRegistry.IPartConverter; +import codechicken.multipart.MultiPartRegistry.IPartFactory; +import codechicken.multipart.MultipartGenerator; +import codechicken.multipart.TMultiPart; +import codechicken.multipart.TileMultipart; + +public class FMP implements IIntegrationModule, IPartFactory, IPartConverter, IFMP +{ + + public static FMP instance; + + @Override + public TMultiPart createPart(String name, boolean client) + { + for (PartRegistry pr : PartRegistry.values()) + { + if ( pr.getName() == name ) + return pr.construct( 0 ); + } + + return null; + } + + @Override + public boolean canConvert(int blockID) + { + return PartRegistry.isPart( Block.blocksList[blockID] ); + } + + @Override + public TMultiPart convert(World world, BlockCoord pos) + { + int blockID = world.getBlockId( pos.x, pos.y, pos.z ); + int meta = world.getBlockMetadata( pos.x, pos.y, pos.z ); + + TMultiPart part = PartRegistry.getPartByBlock( Block.blocksList[blockID], meta ); + if ( part instanceof CableBusPart ) + { + CableBusPart cbp = (CableBusPart) part; + cbp.convertFromTile( world.getBlockTileEntity( pos.x, pos.y, pos.z ) ); + } + + return part; + } + + @Override + public void Init() throws Throwable + { + + } + + @Override + public void PostInit() throws Throwable + { + BlockMicroMaterial.createAndRegister( AEApi.instance().blocks().blockQuartz.block() ); + BlockMicroMaterial.createAndRegister( AEApi.instance().blocks().blockQuartzPiller.block() ); + BlockMicroMaterial.createAndRegister( AEApi.instance().blocks().blockQuartzChiseled.block() ); + + PartRegistry reg[] = PartRegistry.values(); + + String data[] = new String[reg.length]; + for (int x = 0; x < data.length; x++) + data[x] = reg[x].getName(); + + MultiPartRegistry.registerConverter( this ); + MultiPartRegistry.registerParts( this, data ); + MinecraftForge.EVENT_BUS.register( new FMPEvent() ); + // MultipartGenerator.registerPassThroughInterface( "appeng.helpers.AEMultiTile" ); + } + + @Override + public IPartHost getOrCreateHost(TileEntity tile) + { + try + { + BlockCoord loc = new BlockCoord( tile.xCoord, tile.yCoord, tile.zCoord ); + + TileMultipart mp = TileMultipart.getOrConvertTile( tile.worldObj, loc ); + if ( mp != null ) + { + scala.collection.Iterator i = mp.partList().iterator(); + while (i.hasNext()) + { + TMultiPart p = i.next(); + if ( p instanceof CableBusPart ) + return (IPartHost) p; + } + + TMultiPart part = PartRegistry.CableBusPart.construct( 0 ); + if ( mp.canAddPart( part ) && Platform.isServer() ) + TileMultipart.addPart( tile.worldObj, loc, part ); + return (CableBusPart) part; + } + } + catch (Throwable t) + { + t.printStackTrace(); + } + return null; + } + + @Override + public CableBusContainer getCableContainer(TileEntity te) + { + if ( te instanceof TileMultipart ) + { + TileMultipart mp = (TileMultipart) te; + scala.collection.Iterator i = mp.partList().iterator(); + while (i.hasNext()) + { + TMultiPart p = i.next(); + if ( p instanceof CableBusPart ) + return ((CableBusPart) p).cb; + } + } + return null; + } + + @Override + public void registerPassThru(Class layerInterface) + { + try + { + MultipartGenerator.registerPassThroughInterface( layerInterface.getName() ); + } + catch (Throwable t) + { + AELog.severe( "Failed to register " + layerInterface.getName() + " with FMP, some features may not work with MultiParts." ); + t.printStackTrace(); + } + } + +} diff --git a/integration/modules/FZ.java b/integration/modules/FZ.java new file mode 100644 index 00000000..f91c6013 --- /dev/null +++ b/integration/modules/FZ.java @@ -0,0 +1,207 @@ +package appeng.integration.modules; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import appeng.api.AEApi; +import appeng.api.storage.IMEInventory; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IFZ; +import appeng.integration.modules.helpers.FactorizationBarrel; +import appeng.util.Platform; + +/** + * 100% Hacks. + */ +public class FZ implements IFZ, IIntegrationModule +{ + + public static FZ instance; + + private static Class day_BarrelClass; + private static Method day_getItemCount; + private static Method day_setItemCount; + private static Method day_getMaxSize; + private static Field day_item; + + private static Class barrelClass; + private static Method getItemCount; + private static Method setItemCount; + private static Method getMaxSize; + private static Field item; + + @Override + public ItemStack barrelGetItem(TileEntity te) + { + try + { + ItemStack i; + + if ( day_BarrelClass.isInstance( te ) ) i = (ItemStack) day_item.get( te ); + else + i = (ItemStack) item.get( te ); + + if ( i != null ) i = Platform.cloneItemStack( i ); + return i; + } + catch (IllegalArgumentException e) + { + } + catch (IllegalAccessException e) + { + } + return null; + } + + @Override + public int barrelGetMaxItemCount(TileEntity te) + { + try + { + + if ( day_BarrelClass.isInstance( te ) ) return (Integer) day_getMaxSize.invoke( te ); + else + return (Integer) getMaxSize.invoke( te ); + } + catch (IllegalAccessException e) + { + } + catch (IllegalArgumentException e) + { + } + catch (InvocationTargetException e) + { + } + return 0; + } + + @Override + public int barrelGetItemCount(TileEntity te) + { + try + { + + if ( day_BarrelClass.isInstance( te ) ) return (Integer) day_getItemCount.invoke( te ); + else + return (Integer) getItemCount.invoke( te ); + } + catch (IllegalAccessException e) + { + } + catch (IllegalArgumentException e) + { + } + catch (InvocationTargetException e) + { + } + return 0; + } + + @Override + public void setItemType(TileEntity te, ItemStack input) + { + try + { + + if ( day_BarrelClass.isInstance( te ) ) day_item.set( te, input == null ? null : input.copy() ); + else + item.set( te, input == null ? null : input.copy() ); + } + catch (IllegalArgumentException e) + { + } + catch (IllegalAccessException e) + { + } + } + + @Override + public void barrelSetCount(TileEntity te, int max) + { + try + { + + if ( day_BarrelClass.isInstance( te ) ) day_setItemCount.invoke( te, max ); + else + setItemCount.invoke( te, max ); + + te.worldObj.markBlockForUpdate( te.xCoord, te.yCoord, te.zCoord ); + } + catch (IllegalAccessException e) + { + } + catch (IllegalArgumentException e) + { + } + catch (InvocationTargetException e) + { + } + } + + @Override + public IMEInventory getFactorizationBarrel(TileEntity te) + { + return new FactorizationBarrel( this, te ); + } + + @Override + public boolean isBarrel(TileEntity te) + { + if ( day_BarrelClass.isAssignableFrom( te.getClass() ) ) return true; + if ( barrelClass.isAssignableFrom( te.getClass() ) ) return true; + return false; + } + + @Override + public void Init() throws Throwable + { + barrelClass = Class.forName( "factorization.common.TileEntityBarrel" ); + day_BarrelClass = Class.forName( "factorization.common.TileEntityDayBarrel" ); + + getItemCount = barrelClass.getDeclaredMethod( "getItemCount", new Class[] {} ); + setItemCount = barrelClass.getDeclaredMethod( "setItemCount", new Class[] { int.class } ); + getMaxSize = barrelClass.getDeclaredMethod( "getMaxSize", new Class[] {} ); + item = barrelClass.getDeclaredField( "item" ); + + day_getItemCount = day_BarrelClass.getDeclaredMethod( "getItemCount", new Class[] {} ); + day_setItemCount = day_BarrelClass.getDeclaredMethod( "setItemCount", new Class[] { int.class } ); + day_getMaxSize = day_BarrelClass.getDeclaredMethod( "getMaxSize", new Class[] {} ); + day_item = day_BarrelClass.getDeclaredField( "item" ); + } + + @Override + public void PostInit() + { + // certus quartz + grinderRecipe( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + grinderRecipe( AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + // fluix + grinderRecipe( AEApi.instance().materials().materialFluixCrystal.stack( 1 ), + AEApi.instance().materials().materialFluixDust.stack( 1 ) ); + + // nether quartz + grinderRecipe( new ItemStack( Item.netherQuartz ), AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } + + private void grinderRecipe(ItemStack in, ItemStack out) + { + try + { + Class c = Class.forName( "factorization.common.TileEntityGrinder" ); + Method m = c.getMethod( "addRecipe", Object.class, ItemStack.class, float.class ); + m.invoke( c, in, out, 1.0 ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + } +} diff --git a/integration/modules/Forestry.java b/integration/modules/Forestry.java new file mode 100644 index 00000000..28896159 --- /dev/null +++ b/integration/modules/Forestry.java @@ -0,0 +1,24 @@ +package appeng.integration.modules; + +import appeng.integration.IIntegrationModule; + +public class Forestry implements IIntegrationModule +{ + + public static Forestry instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/GT.java b/integration/modules/GT.java new file mode 100644 index 00000000..17740809 --- /dev/null +++ b/integration/modules/GT.java @@ -0,0 +1,44 @@ +package appeng.integration.modules; + +import gregtechmod.api.interfaces.IDigitalChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IMEInventory; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IGT; +import appeng.integration.modules.helpers.GregTechQuantumChest; +import appeng.util.InventoryAdaptor; + +public class GT implements IGT, IIntegrationModule +{ + + public static GT instance; + + @Override + public IMEInventory getQuantumChest(TileEntity te) + { + return new GregTechQuantumChest( (IInventory) te, InventoryAdaptor.getAdaptor( te, ForgeDirection.NORTH ) ); + } + + @Override + public boolean isQuantumChest(TileEntity te) + { + if ( te instanceof IDigitalChest ) + return ((IDigitalChest) te).isDigitalChest(); + return false; + } + + @Override + public void Init() + { + + } + + @Override + public void PostInit() + { + + } + +} diff --git a/integration/modules/IC2.java b/integration/modules/IC2.java new file mode 100644 index 00000000..38cadf88 --- /dev/null +++ b/integration/modules/IC2.java @@ -0,0 +1,44 @@ +package appeng.integration.modules; + +import ic2.api.recipe.RecipeInputItemStack; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.integration.IIntegrationModule; + +public class IC2 implements IIntegrationModule +{ + + public static IC2 instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // certus quartz + maceratorRecipe( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + maceratorRecipe( AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + // fluix + maceratorRecipe( AEApi.instance().materials().materialFluixCrystal.stack( 1 ), + AEApi.instance().materials().materialFluixDust.stack( 1 ) ); + + // nether quartz + maceratorRecipe( new ItemStack( Item.netherQuartz ), AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } + + private void maceratorRecipe(ItemStack in, ItemStack out) + { + ic2.api.recipe.Recipes.macerator.addRecipe( new RecipeInputItemStack( in, in.stackSize ), null, out ); + } + +} diff --git a/integration/modules/InvTweaks.java b/integration/modules/InvTweaks.java new file mode 100644 index 00000000..a122b8e8 --- /dev/null +++ b/integration/modules/InvTweaks.java @@ -0,0 +1,24 @@ +package appeng.integration.modules; + +import appeng.integration.IIntegrationModule; + +public class InvTweaks implements IIntegrationModule +{ + + public static InvTweaks instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/LP.java b/integration/modules/LP.java new file mode 100644 index 00000000..ec2d3db8 --- /dev/null +++ b/integration/modules/LP.java @@ -0,0 +1,24 @@ +package appeng.integration.modules; + +import appeng.integration.IIntegrationModule; + +public class LP implements IIntegrationModule +{ + + public static LP instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/MFR.java b/integration/modules/MFR.java new file mode 100644 index 00000000..93efeec6 --- /dev/null +++ b/integration/modules/MFR.java @@ -0,0 +1,41 @@ +package appeng.integration.modules; + +import net.minecraft.tileentity.TileEntity; +import powercrystals.minefactoryreloaded.api.IDeepStorageUnit; +import appeng.api.storage.IMEInventory; +import appeng.integration.IIntegrationModule; +import appeng.integration.abstraction.IMFR; +import appeng.integration.modules.helpers.MFRDSU; + +public class MFR implements IIntegrationModule, IMFR +{ + + public static MFR instance; + + @Override + public IMEInventory getDSU(TileEntity te) + { + return new MFRDSU( te ); + } + + @Override + public boolean isDSU(TileEntity te) + { + if ( te instanceof IDeepStorageUnit ) return true; + return false; + } + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + + } + +} diff --git a/integration/modules/Mekanism.java b/integration/modules/Mekanism.java new file mode 100644 index 00000000..e7749978 --- /dev/null +++ b/integration/modules/Mekanism.java @@ -0,0 +1,41 @@ +package appeng.integration.modules; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.integration.IIntegrationModule; + +public class Mekanism implements IIntegrationModule +{ + + public static Mekanism instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // certus quartz + crusher( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + crusher( AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + // fluix + crusher( AEApi.instance().materials().materialFluixCrystal.stack( 1 ), AEApi.instance().materials().materialFluixDust.stack( 1 ) ); + + // nether quartz + crusher( new ItemStack( Item.netherQuartz ), AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } + + private void crusher(ItemStack input, ItemStack output) + { + mekanism.api.RecipeHelper.addCrusherRecipe( input, output ); + } +} diff --git a/integration/modules/Mystcraft.java b/integration/modules/Mystcraft.java new file mode 100644 index 00000000..f5c83461 --- /dev/null +++ b/integration/modules/Mystcraft.java @@ -0,0 +1,24 @@ +package appeng.integration.modules; + +import appeng.integration.IIntegrationModule; + +public class Mystcraft implements IIntegrationModule +{ + + public static Mystcraft instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/NEI.java b/integration/modules/NEI.java new file mode 100644 index 00000000..4bdc2ee8 --- /dev/null +++ b/integration/modules/NEI.java @@ -0,0 +1,42 @@ +package appeng.integration.modules; + +import java.lang.reflect.Method; + +import appeng.integration.IIntegrationModule; +import appeng.integration.modules.helpers.NEIQuartzShapedRecipeHandler; + +public class NEI implements IIntegrationModule +{ + + public static NEI instance; + + @Override + public void Init() throws Throwable + { + Class API = Class.forName( "codechicken.nei.api.API" ); + Method registerRecipeHandler = API.getDeclaredMethod( "registerRecipeHandler", new Class[] { codechicken.nei.recipe.ICraftingHandler.class } ); + Method registerUsageHandler = API.getDeclaredMethod( "registerUsageHandler", new Class[] { codechicken.nei.recipe.IUsageHandler.class } ); + + registerRecipeHandler.invoke( API, new NEIQuartzShapedRecipeHandler() ); + registerUsageHandler.invoke( API, new NEIQuartzShapedRecipeHandler() ); + + /* + * Method registerGuiOverlay = API.getDeclaredMethod( "registerGuiOverlay", new Class[] { Class.class, + * String.class, int.class, int.class } ); Class IOverlayHandler = Class.forName( + * "codechicken.nei.api.IOverlayHandler" ); Class DefaultOverlayHandler = + * NEICraftingTerminalOverlayHandler.class; Method registerGuiOverlayHandler = API.getDeclaredMethod( + * "registerGuiOverlayHandler", new Class[] { Class.class, IOverlayHandler, String.class } ); + * registerGuiOverlay.invoke( API, GuiCraftingTerminal.class, "crafting", 6, 75 ); Constructor + * DefaultOverlayHandlerConstructor = DefaultOverlayHandler .getConstructor( new Class[] { int.class, int.class + * } ); registerGuiOverlayHandler.invoke( API, GuiCraftingTerminal.class, + * DefaultOverlayHandlerConstructor.newInstance( 6, 75 ), "crafting" ); + */ + } + + @Override + public void PostInit() throws Throwable + { + + } + +} diff --git a/integration/modules/RC.java b/integration/modules/RC.java new file mode 100644 index 00000000..511ebd1b --- /dev/null +++ b/integration/modules/RC.java @@ -0,0 +1,51 @@ +package appeng.integration.modules; + +import mods.railcraft.api.crafting.IRockCrusherRecipe; +import mods.railcraft.api.crafting.RailcraftCraftingManager; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.integration.IIntegrationModule; + +public class RC implements IIntegrationModule +{ + + public static RC instance; + + public void rockCrusher(ItemStack input, ItemStack output) + { + IRockCrusherRecipe re = RailcraftCraftingManager.rockCrusher.createNewRecipe( input, true, true ); + re.addOutput( output, 1.0f ); + } + + public void rockCrusher(ItemStack input, ItemStack output, ItemStack secondary, float chance) + { + IRockCrusherRecipe re = RailcraftCraftingManager.rockCrusher.createNewRecipe( input, true, true ); + re.addOutput( output, 1.0f ); + if ( secondary != null ) re.addOutput( secondary, chance ); + } + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // certus quartz + rockCrusher( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + rockCrusher( AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + // fluix + rockCrusher( AEApi.instance().materials().materialFluixCrystal.stack( 1 ), AEApi.instance().materials().materialFluixDust.stack( 1 ) ); + + // nether quartz + rockCrusher( new ItemStack( Item.netherQuartz ), AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } +} diff --git a/integration/modules/TE.java b/integration/modules/TE.java new file mode 100644 index 00000000..4b75e1b2 --- /dev/null +++ b/integration/modules/TE.java @@ -0,0 +1,42 @@ +package appeng.integration.modules; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.integration.IIntegrationModule; + +public class TE implements IIntegrationModule +{ + + public static TE instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // certus quartz + pulverizer( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + pulverizer( AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( 1 ), + AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + + // fluix + pulverizer( AEApi.instance().materials().materialFluixCrystal.stack( 1 ), AEApi.instance().materials().materialFluixDust.stack( 1 ) ); + + // nether quartz + pulverizer( new ItemStack( Item.netherQuartz ), AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } + + private void pulverizer(ItemStack in, ItemStack out) + { + thermalexpansion.api.crafting.CraftingManagers.pulverizerManager.addRecipe( 320, in, out ); + } + +} diff --git a/integration/modules/UE.java b/integration/modules/UE.java new file mode 100644 index 00000000..ec087ac8 --- /dev/null +++ b/integration/modules/UE.java @@ -0,0 +1,24 @@ +package appeng.integration.modules; + +import appeng.integration.IIntegrationModule; + +public class UE implements IIntegrationModule +{ + + public static UE instance; + + @Override + public void Init() + { + // TODO Auto-generated method stub + + } + + @Override + public void PostInit() + { + // TODO Auto-generated method stub + + } + +} diff --git a/integration/modules/helpers/BCPipeHandler.java b/integration/modules/helpers/BCPipeHandler.java new file mode 100644 index 00000000..185db8b0 --- /dev/null +++ b/integration/modules/helpers/BCPipeHandler.java @@ -0,0 +1,27 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.integration.modules.BC; + +public class BCPipeHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel chan) + { + return chan == StorageChannel.ITEMS && BC.instance.isPipe( te, d ); + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel chan) + { + if ( chan == StorageChannel.ITEMS ) + return new BCPipeInventory( te, d ); + return null; + } + +} diff --git a/integration/modules/helpers/BCPipeInventory.java b/integration/modules/helpers/BCPipeInventory.java new file mode 100644 index 00000000..ef90d6eb --- /dev/null +++ b/integration/modules/helpers/BCPipeInventory.java @@ -0,0 +1,56 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.integration.modules.BC; + +public class BCPipeInventory implements IMEInventory +{ + + TileEntity te; + ForgeDirection dir; + + public BCPipeInventory(TileEntity _te, ForgeDirection _dir) { + te = _te; + dir = _dir; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + if ( BC.instance.canAddItemsToPipe( te, input.getItemStack(), dir ) ) + return null; + return input; + } + + if ( BC.instance.addItemsToPipe( te, input.getItemStack(), dir ) ) + return null; + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + return out; + } + +} diff --git a/integration/modules/helpers/BSCrate.java b/integration/modules/helpers/BSCrate.java new file mode 100644 index 00000000..78362605 --- /dev/null +++ b/integration/modules/helpers/BSCrate.java @@ -0,0 +1,66 @@ +package appeng.integration.modules.helpers; + +import net.mcft.copy.betterstorage.api.ICrateStorage; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.util.item.AEItemStack; + +public class BSCrate implements IMEInventory +{ + + ICrateStorage cs; + ForgeDirection side; + + public BSCrate(Object object, ForgeDirection d) { + cs = (ICrateStorage) object; + side = d; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + return null; + + ItemStack failed = cs.insertItems( side, input.getItemStack() ); + if ( failed == null ) + return null; + input.setStackSize( failed.stackSize ); + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + int howMany = cs.getItemCount( side, request.getItemStack() ); + return howMany > request.getStackSize() ? request : request.copy().setStackSize( howMany ); + } + + ItemStack Obtained = cs.extractItems( side, request.getItemStack() ); + return AEItemStack.create( Obtained ); + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + for (ItemStack is : cs.getContents( side )) + { + out.add( AEItemStack.create( is ) ); + } + return out; + } + +} diff --git a/integration/modules/helpers/BSCrateHandler.java b/integration/modules/helpers/BSCrateHandler.java new file mode 100644 index 00000000..0b091ee9 --- /dev/null +++ b/integration/modules/helpers/BSCrateHandler.java @@ -0,0 +1,27 @@ +package appeng.integration.modules.helpers; + +import net.mcft.copy.betterstorage.api.ICrateStorage; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; + +public class BSCrateHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel chan) + { + return chan == StorageChannel.ITEMS && te instanceof ICrateStorage; + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel chan) + { + if ( chan == StorageChannel.ITEMS ) + return new BSCrate( te, ForgeDirection.UNKNOWN ); + return null; + } + +} diff --git a/integration/modules/helpers/BSCrateStorageAdaptor.java b/integration/modules/helpers/BSCrateStorageAdaptor.java new file mode 100644 index 00000000..f565602b --- /dev/null +++ b/integration/modules/helpers/BSCrateStorageAdaptor.java @@ -0,0 +1,185 @@ +package appeng.integration.modules.helpers; + +import java.util.Iterator; + +import net.mcft.copy.betterstorage.api.ICrateStorage; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.inv.IInventoryDestination; +import appeng.util.inv.ItemSlot; +import appeng.util.iterators.StackToSlotIterator; + +public class BSCrateStorageAdaptor extends InventoryAdaptor +{ + + ICrateStorage cs; + ForgeDirection side; + + public BSCrateStorageAdaptor(Object te, ForgeDirection d) { + cs = (ICrateStorage) te; + side = d; + } + + @Override + public ItemStack removeItems(int how_many, ItemStack Filter, IInventoryDestination dest) + { + ItemStack target = null; + + for (ItemStack is : cs.getContents( side )) + { + if ( is != null ) + { + if ( is.stackSize > 0 && (Filter == null || Platform.isSameItem( Filter, is )) ) + { + if ( dest == null || dest.canInsert( is ) ) + { + target = is; + break; + } + } + } + } + + if ( target != null ) + { + ItemStack f = Platform.cloneItemStack( target ); + f.stackSize = how_many; + return cs.extractItems( side, f ); + } + + return null; + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack Filter, IInventoryDestination dest) + { + ItemStack target = null; + + for (ItemStack is : cs.getContents( side )) + { + if ( is != null ) + { + if ( is.stackSize > 0 && (Filter == null || Platform.isSameItem( Filter, is )) ) + { + if ( dest == null || dest.canInsert( is ) ) + { + target = is; + break; + } + } + } + } + + if ( target != null ) + { + int cnt = cs.getItemCount( side, target ); + if ( cnt == 0 ) + return null; + if ( cnt > how_many ) + cnt = how_many; + ItemStack c = target.copy(); + c.stackSize = cnt; + return c; + } + + return null; + } + + @Override + public ItemStack removeSimilarItems(int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + ItemStack target = null; + + for (ItemStack is : cs.getContents( side )) + { + if ( is != null ) + { + if ( is.stackSize > 0 && (filter == null || Platform.isSameItemFuzzy( filter, is, fuzzyMode )) ) + { + if ( dest == null || dest.canInsert( is ) ) + { + target = is; + break; + } + } + } + } + + if ( target != null ) + { + ItemStack f = Platform.cloneItemStack( target ); + f.stackSize = amount; + return cs.extractItems( side, f ); + } + + return null; + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + ItemStack target = null; + + for (ItemStack is : cs.getContents( side )) + { + if ( is != null ) + { + if ( is.stackSize > 0 && (filter == null || Platform.isSameItemFuzzy( filter, is, fuzzyMode )) ) + { + if ( dest == null || dest.canInsert( is ) ) + { + target = is; + break; + } + } + } + } + + if ( target != null ) + { + int cnt = cs.getItemCount( side, target ); + if ( cnt == 0 ) + return null; + if ( cnt > how_many ) + cnt = how_many; + ItemStack c = target.copy(); + c.stackSize = cnt; + return c; + } + + return null; + } + + @Override + public ItemStack addItems(ItemStack A) + { + return cs.insertItems( side, A ); + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + int items = cs.spaceForItem( side, A ); + ItemStack B = Platform.cloneItemStack( A ); + if ( A.stackSize <= items ) + return null; + B.stackSize -= items; + return B; + } + + @Override + public boolean containsItems() + { + return cs.getContents( side ).size() > 0; + } + + @Override + public Iterator iterator() + { + return new StackToSlotIterator( cs.getContents( side ).iterator() ); + } + +} diff --git a/integration/modules/helpers/FMPPacketEvent.java b/integration/modules/helpers/FMPPacketEvent.java new file mode 100644 index 00000000..8a45d982 --- /dev/null +++ b/integration/modules/helpers/FMPPacketEvent.java @@ -0,0 +1,15 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.event.Event; + +public class FMPPacketEvent extends Event +{ + + public final EntityPlayerMP sender; + + public FMPPacketEvent(EntityPlayerMP sender) { + this.sender = sender; + } + +} diff --git a/integration/modules/helpers/FacadeProxyBC.java b/integration/modules/helpers/FacadeProxyBC.java new file mode 100644 index 00000000..cf05349f --- /dev/null +++ b/integration/modules/helpers/FacadeProxyBC.java @@ -0,0 +1,400 @@ +package appeng.integration.modules.helpers; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import buildcraft.transport.ItemFacade; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class FacadeProxyBC implements IFacadeProxy +{ + + float facadeThickness = 1F / 16F; + + int facadeBlocks[]; + int facadeMeta[]; + + public FacadeProxyBC() { + facadeBlocks = new int[6]; + facadeMeta = new int[6]; + } + + /** + * Mirrors the array on the Y axis by calculating offsets from 0.5F + * + * @param targetArray + */ + private void mirrorY(float[][] targetArray) + { + float temp = targetArray[1][0]; + targetArray[1][0] = (targetArray[1][1] - 0.5F) * -1F + 0.5F; // 1 -> + // 0.5F + // -> + // -0.5F + // -> 0F + targetArray[1][1] = (temp - 0.5F) * -1F + 0.5F; // 0 -> -0.5F -> 0.5F -> + // 1F + } + + /** + * Shifts the coordinates around effectivly rotating something. Zero state + * is DOWN then -> NORTH -> WEST Note - To obtain Pos, do a mirrorY() before + * rotating + * + * @param targetArray + * the array that should be rotated + */ + private void rotate(float[][] targetArray) + { + for (int i = 0; i < 2; i++) + { + float temp = targetArray[2][i]; + targetArray[2][i] = targetArray[1][i]; + targetArray[1][i] = targetArray[0][i]; + targetArray[0][i] = temp; + } + } + + /** + * @param targetArray + * the array that should be transformed + * @param direction + */ + private void transform(float[][] targetArray, ForgeDirection direction) + { + if ( (direction.ordinal() & 0x1) == 1 ) + { + mirrorY( targetArray ); + } + + for (int i = 0; i < (direction.ordinal() >> 1); i++) + { + rotate( targetArray ); + } + } + + /** + * Clones both dimensions of a float[][] + * + * @param source + * the float[][] to deepClone + * @return + */ + private float[][] deepClone(float[][] source) + { + float[][] target = source.clone(); + for (int i = 0; i < target.length; i++) + { + target[i] = source[i].clone(); + } + return target; + } + + @Override + @SideOnly(Side.CLIENT) + public void facadeRender(RenderBlocks renderblocks, Block block, IFacadeTile ft, int x, int y, int z, float tubeThickness) + { + float zFightOffset = 1F / 4096F; + + float[][] zeroState = new float[3][2]; + // X START - END + zeroState[0][0] = 0.0F - zFightOffset / 2; + zeroState[0][1] = 1.0F + zFightOffset / 2; + // Y START - END + zeroState[1][0] = 0.0F - zFightOffset; + zeroState[1][1] = facadeThickness; + // Z START - END + zeroState[2][0] = 0.0F; + zeroState[2][1] = 1.0F; + + renderblocks.renderAllFaces = true; + + for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + if ( hasFacade( ft, direction ) ) + { + Block blk = Block.blocksList[facadeBlocks[direction.ordinal()]]; + renderblocks.overrideBlockTexture = blk.getIcon( direction.ordinal(), facadeMeta[direction.ordinal()] ); + + try + { + // AppEngBlockRenderer.instance.overrideRenderColor = + // Item.itemsList[ facadeBlocks[ direction.ordinal() ] + // ].getColorFromItemStack(new ItemStack( facadeBlocks[ + // direction.ordinal() ], 1, facadeMeta[ direction.ordinal() + // ] ), 0); + } catch (Throwable error) + { + // explosion! + } + + if ( blk.getRenderType() == 31 ) + { + if ( (facadeMeta[direction.ordinal()] & 12) == 4 ) + { + renderblocks.uvRotateEast = 1; + renderblocks.uvRotateWest = 1; + renderblocks.uvRotateTop = 1; + renderblocks.uvRotateBottom = 1; + } else if ( (facadeMeta[direction.ordinal()] & 12) == 8 ) + { + renderblocks.uvRotateSouth = 1; + renderblocks.uvRotateNorth = 1; + } + } + + float holeThickness = ft.getHoleThickness( direction ); + + // Hollow facade + if ( ft.isConnected( direction ) ) + { + float[][] rotated = deepClone( zeroState ); + rotated[2][0] = 0.0F; + rotated[2][1] = 0.0f + holeThickness; + rotated[1][0] -= zFightOffset / 2; + transform( rotated, direction ); + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + + rotated = deepClone( zeroState ); + rotated[2][0] = 1.0f - holeThickness; + rotated[1][0] -= zFightOffset / 2; + transform( rotated, direction ); + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + + rotated = deepClone( zeroState ); + rotated[0][0] = 0.0F; + rotated[0][1] = 0.0f + holeThickness; + rotated[1][1] -= zFightOffset; + transform( rotated, direction ); + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + + rotated = deepClone( zeroState ); + rotated[0][0] = 1.0f - holeThickness; + rotated[0][1] = 1F; + rotated[1][1] -= zFightOffset; + transform( rotated, direction ); + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + } else + { // Solid facade + float[][] rotated = deepClone( zeroState ); + transform( rotated, direction ); + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + } + + // AppEngBlockRenderer.instance.overrideRenderColor = -1; + } + + renderblocks.uvRotateEast = 0; + renderblocks.uvRotateWest = 0; + renderblocks.uvRotateTop = 0; + renderblocks.uvRotateBottom = 0; + renderblocks.uvRotateSouth = 0; + renderblocks.uvRotateNorth = 0; + } + + // X START - END + zeroState[0][0] = 0.0f + tubeThickness; // Utils.pipeMinPos; + zeroState[0][1] = 1.0f - tubeThickness; // Utils.pipeMaxPos; + // Y START - END + zeroState[1][0] = facadeThickness; + zeroState[1][1] = 0.0f + tubeThickness; // Utils.pipeMinPos; + // Z START - END + zeroState[2][0] = 0.0f + tubeThickness; // Utils.pipeMinPos; + zeroState[2][1] = 1.0f - tubeThickness; // Utils.pipeMaxPos; + + if ( tubeThickness > 0.001 ) + { + // renderblocks.overrideBlockTexture = + // BuildCraftTransport.instance.pipeIconProvider.getIcon(PipeIconProvider.PipeStructureCobblestone); + // // Structure Pipe + + for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + if ( hasFacade( ft, direction ) && !ft.isConnected( direction ) ) + { + float[][] rotated = deepClone( zeroState ); + transform( rotated, direction ); + + block.setBlockBounds( rotated[0][0], rotated[1][0], rotated[2][0], rotated[0][1], rotated[1][1], + rotated[2][1] ); + renderblocks.setRenderBoundsFromBlock( block ); + renderblocks.renderStandardBlock( block, x, y, z ); + } + } + } + + renderblocks.renderAllFaces = false; + renderblocks.overrideBlockTexture = null; + } + + ItemStack createFacade(int itemid, int meta) + { + try + { + return ItemFacade.getStack( itemid, meta ); + } catch (Throwable e) + { + try + { + // return new ItemStack( BuildCraftTransport.facadeItem, 1, + // ItemFacade.encode( itemid, meta ) ); + } catch (Throwable e2) + { + FMLLog.severe( "Unable to create facade item, please make sure your using the newest Version of BC and AE, and if you are inform AlgorithmX2 of this message." ); + } + } + return null; + } + + @Override + public List getDrops(IFacadeTile ft) + { + List out = new ArrayList(); + + for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + if ( this.facadeBlocks[direction.ordinal()] != 0 ) + { + ItemStack facade = createFacade( this.facadeBlocks[direction.ordinal()], this.facadeMeta[direction.ordinal()] ); + + this.facadeMeta[direction.ordinal()] = 0; + + out.add( facade ); + } + } + + return out; + } + + @Override + public boolean addFacade(IFacadeTile ft, ForgeDirection direction, int blockid, int meta) + { + if ( hasFacade( ft, direction ) ) + dropFacade( ft, direction ); + + // if ( ft.isConnected( direction ) ) + // return false; + + this.facadeBlocks[direction.ordinal()] = blockid; + this.facadeMeta[direction.ordinal()] = meta; + + ft.markForUpdate(); + + return true; + } + + @Override + public boolean hasFacade(IFacadeTile ft, ForgeDirection direction) + { + return this.facadeBlocks[direction.ordinal()] != 0; + } + + @Override + public void dropFacade(IFacadeTile ft, ForgeDirection direction) + { + if ( this.facadeBlocks[direction.ordinal()] != 0 ) + { + ItemStack facade = createFacade( this.facadeBlocks[direction.ordinal()], this.facadeMeta[direction.ordinal()] ); + + this.facadeBlocks[direction.ordinal()] = 0; + this.facadeMeta[direction.ordinal()] = 0; + + ft.dropFacadeItem( facade ); + + ft.markForUpdate(); + } + } + + @Override + public boolean readFromStream(DataInputStream out) throws IOException + { + boolean diffrent = false; + for (int x = 0; x < 6; x++) + { + int fb = facadeBlocks[x]; + int fm = facadeMeta[x]; + facadeBlocks[x] = out.readInt(); + facadeMeta[x] = out.readInt(); + diffrent = diffrent || fb != facadeBlocks[x] || fm != facadeMeta[x]; + } + return diffrent; + } + + @Override + public void writeToStream(DataOutputStream out) throws IOException + { + for (int x = 0; x < 6; x++) + { + out.writeInt( facadeBlocks[x] ); + out.writeInt( facadeMeta[x] ); + } + } + + @Override + public void writeToNBT(NBTTagCompound tc) + { + tc.setIntArray( "facadeBlocks", facadeBlocks ); + tc.setIntArray( "facadeMeta", facadeMeta ); + } + + @Override + public void readFromNBT(NBTTagCompound tc) + { + facadeBlocks = tc.getIntArray( "facadeBlocks" ); + facadeMeta = tc.getIntArray( "facadeMeta" ); + + if ( facadeBlocks == null ) + facadeBlocks = new int[6]; + if ( facadeMeta == null ) + facadeMeta = new int[6]; + if ( facadeBlocks.length != 6 ) + facadeBlocks = new int[6]; + if ( facadeMeta.length != 6 ) + facadeMeta = new int[6]; + } + + @Override + public boolean addFacade(TileEntity tileEntity, int side, ItemStack hand) + { + if ( tileEntity instanceof IFacadeTile ) + { + + try + { + return addFacade( (IFacadeTile) tileEntity, ForgeDirection.getOrientation( side ), ItemFacade.getBlockId( hand ), + ItemFacade.getMetaData( hand ) ); + } catch (Throwable e) + { + FMLLog.severe( "Unable to place facade item, please make sure your using the newest Version of BC and AE, and if you are inform AlgorithmX2 of this message." ); + } + } + return false; + } + +} diff --git a/integration/modules/helpers/FacadeProxyNull.java b/integration/modules/helpers/FacadeProxyNull.java new file mode 100644 index 00000000..52c357a0 --- /dev/null +++ b/integration/modules/helpers/FacadeProxyNull.java @@ -0,0 +1,83 @@ +package appeng.integration.modules.helpers; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class FacadeProxyNull implements IFacadeProxy +{ + + @Override + @SideOnly(Side.CLIENT) + public void facadeRender(RenderBlocks renderblocks, Block block, IFacadeTile ft, int x, int y, int z, float th) + { + + } + + @Override + public List getDrops(IFacadeTile ft) + { + return new ArrayList(); + } + + @Override + public boolean addFacade(IFacadeTile ft, ForgeDirection direction, int blockid, int meta) + { + + return false; + } + + @Override + public boolean hasFacade(IFacadeTile ft, ForgeDirection direction) + { + return false; + } + + @Override + public void dropFacade(IFacadeTile ft, ForgeDirection direction) + { + + } + + @Override + public void writeToNBT(NBTTagCompound tc) + { + + } + + @Override + public void writeToStream(DataOutputStream out) throws IOException + { + + } + + @Override + public boolean readFromStream(DataInputStream out) throws IOException + { + return false; + } + + @Override + public void readFromNBT(NBTTagCompound tc) + { + + } + + @Override + public boolean addFacade(TileEntity tileEntity, int side, ItemStack hand) + { + return false; + } + +} diff --git a/integration/modules/helpers/FactorizationBarrel.java b/integration/modules/helpers/FactorizationBarrel.java new file mode 100644 index 00000000..40d865e6 --- /dev/null +++ b/integration/modules/helpers/FactorizationBarrel.java @@ -0,0 +1,132 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.integration.abstraction.IFZ; +import appeng.util.item.AEItemStack; + +public class FactorizationBarrel implements IMEInventory +{ + + private final TileEntity te; + IFZ fProxy; + + public FactorizationBarrel(IFZ proxy, TileEntity tile) { + te = tile; + fProxy = proxy; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + public long remainingItemTypes() + { + return fProxy.barrelGetItem( te ) == null ? 1 : 0; + } + + public long remainingItemCount() + { + return fProxy.barrelGetMaxItemCount( te ) - fProxy.barrelGetItemCount( te ); + } + + public boolean containsItemType(IAEItemStack i) + { + return i.equals( fProxy.barrelGetItem( te ) ); + } + + public long storedItemCount() + { + return fProxy.barrelGetItemCount( te ); + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + if ( input == null ) + return null; + if ( input.getStackSize() == 0 ) + return null; + + ItemStack shared = input.getItemStack(); + if ( shared.isItemDamaged() ) + return input; + + if ( remainingItemTypes() > 0 ) + { + if ( mode == Actionable.MODULATE ) + fProxy.setItemType( te, input.getItemStack() ); + } + + if ( containsItemType( input ) ) + { + int max = fProxy.barrelGetMaxItemCount( te ); + int newTotal = (int) storedItemCount() + (int) input.getStackSize(); + if ( newTotal > max ) + { + if ( mode == Actionable.MODULATE ) + fProxy.barrelSetCount( te, max ); + IAEItemStack result = input.copy(); + result.setStackSize( newTotal - max ); + return result; + } + else + { + if ( mode == Actionable.MODULATE ) + fProxy.barrelSetCount( te, newTotal ); + return null; + } + } + + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + if ( containsItemType( request ) ) + { + int howMany = (int) storedItemCount(); + if ( request.getStackSize() >= howMany ) + { + if ( mode == Actionable.MODULATE ) + { + fProxy.setItemType( te, null ); + fProxy.barrelSetCount( te, 0 ); + } + + IAEItemStack r = request.copy(); + r.setStackSize( howMany ); + return r; + } + else + { + if ( mode == Actionable.MODULATE ) + fProxy.barrelSetCount( te, (int) (howMany - request.getStackSize()) ); + return request.copy(); + } + } + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + ItemStack i = fProxy.barrelGetItem( te ); + if ( i != null ) + { + i.stackSize = fProxy.barrelGetItemCount( te ); + out.addStorage( AEItemStack.create( i ) ); + } + + return out; + } + +} \ No newline at end of file diff --git a/integration/modules/helpers/FactorizationHandler.java b/integration/modules/helpers/FactorizationHandler.java new file mode 100644 index 00000000..017d8d15 --- /dev/null +++ b/integration/modules/helpers/FactorizationHandler.java @@ -0,0 +1,27 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.integration.modules.FZ; + +public class FactorizationHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel chan) + { + return chan == StorageChannel.ITEMS && FZ.instance.isBarrel( te ); + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel chan) + { + if ( chan == StorageChannel.ITEMS ) + return FZ.instance.getFactorizationBarrel( te ); + return null; + } + +} diff --git a/integration/modules/helpers/ForestryGeneticsComparison.java b/integration/modules/helpers/ForestryGeneticsComparison.java new file mode 100644 index 00000000..d9544500 --- /dev/null +++ b/integration/modules/helpers/ForestryGeneticsComparison.java @@ -0,0 +1,47 @@ +package appeng.integration.modules.helpers; + +import appeng.api.features.IItemComparison; +import appeng.api.integration.IBeeComparison; +import forestry.api.arboriculture.EnumTreeChromosome; +import forestry.api.genetics.IIndividual; + +public class ForestryGeneticsComparison implements IItemComparison, IBeeComparison +{ + + IIndividual idiv; + String Species; + + @Override + public IIndividual getIndividual() + { + return idiv; + } + + public ForestryGeneticsComparison(IIndividual _idiv) { + idiv = _idiv; + Species = _idiv.getGenome().getActiveAllele( EnumTreeChromosome.SPECIES.ordinal() ).getUID(); + } + + @Override + public boolean sameAsPrecise(IItemComparison comp) + { + if ( comp instanceof ForestryGeneticsComparison ) + { + IIndividual op = ((ForestryGeneticsComparison) comp).idiv; + if ( idiv.isAnalyzed() == op.isAnalyzed() ) + return idiv.isGeneticEqual( op ); + } + + return false; + } + + @Override + public boolean sameAsFuzzy(IItemComparison comp) + { + if ( comp instanceof ForestryGeneticsComparison ) + return Species.equals( ((ForestryGeneticsComparison) comp).Species ); + + return false; + } + +} diff --git a/integration/modules/helpers/ForestryGeneticsProvider.java b/integration/modules/helpers/ForestryGeneticsProvider.java new file mode 100644 index 00000000..9a22a4b8 --- /dev/null +++ b/integration/modules/helpers/ForestryGeneticsProvider.java @@ -0,0 +1,32 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.item.ItemStack; +import appeng.api.features.IItemComparisionProvider; +import appeng.api.features.IItemComparison; +import forestry.api.genetics.IIndividual; + +public class ForestryGeneticsProvider implements IItemComparisionProvider +{ + + @Override + public IItemComparison getComparison(ItemStack is) + { + if ( forestry.api.genetics.AlleleManager.alleleRegistry != null ) + { + IIndividual idiv = forestry.api.genetics.AlleleManager.alleleRegistry.getIndividual( is ); + if ( idiv == null ) + return null; + return new ForestryGeneticsComparison( idiv ); + } + return null; + } + + @Override + public boolean canHandle(ItemStack stack) + { + if ( forestry.api.genetics.AlleleManager.alleleRegistry != null ) + return forestry.api.genetics.AlleleManager.alleleRegistry.isIndividual( stack ); + return false; + } + +} diff --git a/integration/modules/helpers/GregTechHandler.java b/integration/modules/helpers/GregTechHandler.java new file mode 100644 index 00000000..a1f3fdba --- /dev/null +++ b/integration/modules/helpers/GregTechHandler.java @@ -0,0 +1,27 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.integration.modules.GT; + +public class GregTechHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel chan) + { + return chan == StorageChannel.ITEMS && GT.instance.isQuantumChest( te ); + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel chan) + { + if ( chan == StorageChannel.ITEMS ) + return GT.instance.getQuantumChest( te ); + return null; + } + +} diff --git a/integration/modules/helpers/GregTechQuantumChest.java b/integration/modules/helpers/GregTechQuantumChest.java new file mode 100644 index 00000000..f089f6c6 --- /dev/null +++ b/integration/modules/helpers/GregTechQuantumChest.java @@ -0,0 +1,103 @@ +package appeng.integration.modules.helpers; + +import gregtechmod.api.interfaces.IDigitalChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import appeng.api.config.Actionable; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.me.storage.MEIInventoryWrapper; +import appeng.util.InventoryAdaptor; +import appeng.util.item.AEItemStack; + +public class GregTechQuantumChest extends MEIInventoryWrapper +{ + + IDigitalChest qc; + + public GregTechQuantumChest(IInventory m, InventoryAdaptor ia) { + super( m, ia ); + qc = (IDigitalChest) m; + } + + private ItemStack getType() + { + ItemStack[] array = qc.getStoredItemData(); + if ( array.length > 0 && array[0].itemID > 0 ) + return array[0]; + return null; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + ItemStack type = getType(); + if ( input.hasTagCompound() ) + return input; + + if ( type == null ) + { + return input; + } + + if ( (type.getItem() == input.getItem() && type.getItemDamage() == input.getItemDamage()) ) + { + if ( type.stackSize < qc.getMaxItemCount() ) + { + int room = (int) ((long) qc.getMaxItemCount() - (long) type.stackSize); + if ( input.getStackSize() > room ) + { + IAEItemStack is = input.copy(); + is.setStackSize( is.getStackSize() - room ); + if ( mode == Actionable.MODULATE ) + qc.setItemCount( type.stackSize + room ); + + return super.injectItems( is, mode ); + } + + if ( mode == Actionable.MODULATE ) + qc.setItemCount( type.stackSize + (int) input.getStackSize() ); + + return null; + } + + return super.injectItems( input, mode ); + } + + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack i, Actionable mode) + { + ItemStack type = getType(); + if ( type != null ) + { + if ( type.getItem() == i.getItem() && type.getItemDamage() == i.getItemDamage() ) + { + if ( type.stackSize > i.getStackSize() ) + { + IAEItemStack output = AEItemStack.create( type ); + output.setStackSize( (int) i.getStackSize() ); + if ( mode == Actionable.MODULATE ) + qc.setItemCount( type.stackSize - (int) output.getStackSize() ); + return output; + } + } + } + return super.extractItems( i, mode ); + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + ItemStack type = getType(); + if ( type != null ) + { + super.getAvailableItems( out ); + if ( type != null && type.stackSize > 0 ) + out.addStorage( AEItemStack.create( type ) ); + } + return out; + } +} \ No newline at end of file diff --git a/integration/modules/helpers/IFacadeProxy.java b/integration/modules/helpers/IFacadeProxy.java new file mode 100644 index 00000000..e4bf7bde --- /dev/null +++ b/integration/modules/helpers/IFacadeProxy.java @@ -0,0 +1,41 @@ +package appeng.integration.modules.helpers; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public interface IFacadeProxy +{ + + @SideOnly(Side.CLIENT) + void facadeRender(RenderBlocks renderblocks, Block block, IFacadeTile ft, int x, int y, int z, float tubeThickness); + + List getDrops(IFacadeTile ft); + + boolean addFacade(IFacadeTile ft, ForgeDirection direction, int blockid, int meta); + + boolean hasFacade(IFacadeTile ft, ForgeDirection direction); + + void dropFacade(IFacadeTile ft, ForgeDirection direction); + + void writeToNBT(NBTTagCompound tc); + + void writeToStream(DataOutputStream out) throws IOException; + + boolean readFromStream(DataInputStream out) throws IOException; + + void readFromNBT(NBTTagCompound tc); + + boolean addFacade(TileEntity tileEntity, int side, ItemStack hand); + +} diff --git a/integration/modules/helpers/IFacadeTile.java b/integration/modules/helpers/IFacadeTile.java new file mode 100644 index 00000000..1b5776a2 --- /dev/null +++ b/integration/modules/helpers/IFacadeTile.java @@ -0,0 +1,19 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; + +public interface IFacadeTile +{ + + boolean isConnected(ForgeDirection direction); + + void dropFacadeItem(ItemStack facade); + + IFacadeProxy getFacadeProxy(); + + void markForUpdate(); + + float getHoleThickness(ForgeDirection direction); + +} diff --git a/integration/modules/helpers/MFRDSU.java b/integration/modules/helpers/MFRDSU.java new file mode 100644 index 00000000..58009141 --- /dev/null +++ b/integration/modules/helpers/MFRDSU.java @@ -0,0 +1,101 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import powercrystals.minefactoryreloaded.api.IDeepStorageUnit; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.util.item.AEItemStack; + +public class MFRDSU implements IMEInventory +{ + + IDeepStorageUnit dsu; + TileEntity te; + + public MFRDSU(TileEntity ta) { + te = ta; + dsu = (IDeepStorageUnit) ta; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + ItemStack is = dsu.getStoredItemType(); + if ( is != null ) + { + if ( input.equals( is ) ) + { + long max = dsu.getMaxStoredCount(); + long additiona = is.stackSize; + additiona += input.getStackSize(); + if ( additiona > max ) + { + IAEItemStack overflow = AEItemStack.create( is ); + overflow.setStackSize( (int) (additiona - max) ); + if ( mode == Actionable.MODULATE ) + dsu.setStoredItemCount( (int) max ); + return overflow; + } + else + { + if ( mode == Actionable.MODULATE ) + dsu.setStoredItemCount( is.stackSize + (int) input.getStackSize() ); + return null; + } + } + } + else + { + if ( input.getTagCompound() != null ) + return input; + if ( mode == Actionable.MODULATE ) + dsu.setStoredItemType( input.getItemStack(), (int) input.getStackSize() ); + return null; + } + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + ItemStack is = dsu.getStoredItemType(); + if ( request.equals( is ) ) + { + if ( request.getStackSize() >= is.stackSize ) + { + if ( mode == Actionable.MODULATE ) + dsu.setStoredItemCount( 0 ); + return AEItemStack.create( is ); + } + else + { + if ( mode == Actionable.MODULATE ) + dsu.setStoredItemCount( is.stackSize - (int) request.getStackSize() ); + return request.copy(); + } + } + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + ItemStack is = dsu.getStoredItemType(); + if ( is != null ) + { + out.add( AEItemStack.create( is ) ); + } + return out; + } + +} diff --git a/integration/modules/helpers/MFRDSUHandler.java b/integration/modules/helpers/MFRDSUHandler.java new file mode 100644 index 00000000..11fa9bd5 --- /dev/null +++ b/integration/modules/helpers/MFRDSUHandler.java @@ -0,0 +1,27 @@ +package appeng.integration.modules.helpers; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.integration.modules.MFR; + +public class MFRDSUHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel chan) + { + return chan == StorageChannel.ITEMS && MFR.instance.isDSU( te ); + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel chan) + { + if ( chan == StorageChannel.ITEMS ) + return MFR.instance.getDSU( te ); + return null; + } + +} diff --git a/integration/modules/helpers/NEICraftingTerminalOverlayHandler.java b/integration/modules/helpers/NEICraftingTerminalOverlayHandler.java new file mode 100644 index 00000000..25a0626f --- /dev/null +++ b/integration/modules/helpers/NEICraftingTerminalOverlayHandler.java @@ -0,0 +1,84 @@ +package appeng.integration.modules.helpers; + +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.nbt.NBTTagCompound; +import appeng.container.slot.SlotCraftingMatrix; +import codechicken.nei.PositionedStack; +import codechicken.nei.api.IOverlayHandler; +import codechicken.nei.recipe.IRecipeHandler; +import cpw.mods.fml.common.network.PacketDispatcher; + +public class NEICraftingTerminalOverlayHandler implements IOverlayHandler +{ + + public NEICraftingTerminalOverlayHandler(int x, int y) { + offsetx = x; + offsety = y; + } + + int offsetx; + int offsety; + + // @override + public void overlayRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, boolean shift) + { + try + { + List ingredients = recipe.getIngredientStacks( recipeIndex ); + overlayRecipe( gui, ingredients, shift ); + } + catch (Exception err) + { + } + catch (Error err) + { + } + } + + // @override + public void overlayRecipe(GuiContainer gui, List ingredients, boolean shift) + { + try + { + NBTTagCompound recipe = new NBTTagCompound(); + + if ( gui instanceof GuiTerminal ) + { + for (int i = 0; i < ingredients.size(); i++)// identify slots + { + LinkedList recipeSlots = new LinkedList(); + PositionedStack pstack = ingredients.get( i ); + if ( pstack.item != null ) + { + for (Slot slot : (List) gui.inventorySlots.inventorySlots) + { + if ( slot.xDisplayPosition == pstack.relx + offsetx && slot.yDisplayPosition == pstack.rely + offsety ) + { + if ( slot instanceof SlotCraftingMatrix ) + { + NBTTagCompound inbt = new NBTTagCompound(); + pstack.item.writeToNBT( inbt ); + recipe.setCompoundTag( "#" + ((SlotCraftingMatrix) slot).matrixID, inbt ); + break; + } + } + } + } + } + + PacketDispatcher.sendPacketToServer( (new PacketNEIRecipe( recipe )).getPacket() ); + } + } + catch (Exception err) + { + } + catch (Error err) + { + } + } + +} diff --git a/integration/modules/helpers/NEIQuartzShapedRecipeHandler.java b/integration/modules/helpers/NEIQuartzShapedRecipeHandler.java new file mode 100644 index 00000000..1869f17d --- /dev/null +++ b/integration/modules/helpers/NEIQuartzShapedRecipeHandler.java @@ -0,0 +1,209 @@ +package appeng.integration.modules.helpers; + +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; +import appeng.recipes.AEShapedQuartzRecipe; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.NEIServerUtils; +import codechicken.nei.PositionedStack; +import codechicken.nei.api.DefaultOverlayRenderer; +import codechicken.nei.api.IOverlayHandler; +import codechicken.nei.api.IRecipeOverlayRenderer; +import codechicken.nei.api.IStackPositioner; +import codechicken.nei.recipe.RecipeInfo; +import codechicken.nei.recipe.TemplateRecipeHandler; + +public class NEIQuartzShapedRecipeHandler extends TemplateRecipeHandler +{ + + public void loadTransferRects() + { + this.transferRects.add( new TemplateRecipeHandler.RecipeTransferRect( new Rectangle( 84, 23, 24, 18 ), "crafting", new Object[0] ) ); + } + + public Class getGuiClass() + { + return GuiCrafting.class; + } + + @Override + public String getRecipeName() + { + return NEIClientUtils.translate( "recipe.shaped", new Object[0] ); + } + + @Override + public void loadCraftingRecipes(String outputId, Object[] results) + { + if ( (outputId.equals( "crafting" )) && (getClass() == NEIQuartzShapedRecipeHandler.class) ) + { + List allrecipes = CraftingManager.getInstance().getRecipeList(); + for (IRecipe irecipe : allrecipes) + { + CachedShapedRecipe recipe = null; + if ( (irecipe instanceof AEShapedQuartzRecipe) ) + recipe = new CachedShapedRecipe( (AEShapedQuartzRecipe) irecipe ); + + if ( recipe != null ) + { + recipe.computeVisuals(); + this.arecipes.add( recipe ); + } + } + } + else + { + super.loadCraftingRecipes( outputId, results ); + } + } + + public void loadCraftingRecipes(ItemStack result) + { + List allrecipes = CraftingManager.getInstance().getRecipeList(); + for (IRecipe irecipe : allrecipes) + { + if ( NEIServerUtils.areStacksSameTypeCrafting( irecipe.getRecipeOutput(), result ) ) + { + CachedShapedRecipe recipe = null; + if ( (irecipe instanceof AEShapedQuartzRecipe) ) + recipe = new CachedShapedRecipe( (AEShapedQuartzRecipe) irecipe ); + + if ( recipe != null ) + { + recipe.computeVisuals(); + this.arecipes.add( recipe ); + } + } + } + } + + public void loadUsageRecipes(ItemStack ingredient) + { + List allrecipes = CraftingManager.getInstance().getRecipeList(); + for (IRecipe irecipe : allrecipes) + { + CachedShapedRecipe recipe = null; + if ( (irecipe instanceof AEShapedQuartzRecipe) ) + recipe = new CachedShapedRecipe( (AEShapedQuartzRecipe) irecipe ); + + if ( (recipe != null) && (recipe.contains( recipe.ingredients, ingredient.itemID )) ) + { + recipe.computeVisuals(); + if ( recipe.contains( recipe.ingredients, ingredient ) ) + { + recipe.setIngredientPermutation( recipe.ingredients, ingredient ); + this.arecipes.add( recipe ); + } + } + } + } + + public String getGuiTexture() + { + return "textures/gui/container/crafting_table.png"; + } + + public String getOverlayIdentifier() + { + return "crafting"; + } + + @Override + public boolean hasOverlay(GuiContainer gui, Container container, int recipe) + { + return (super.hasOverlay( gui, container, recipe )) || ((isRecipe2x2( recipe )) && (RecipeInfo.hasDefaultOverlay( gui, "crafting2x2" ))); + } + + @Override + public IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe) + { + IRecipeOverlayRenderer renderer = super.getOverlayRenderer( gui, recipe ); + if ( renderer != null ) + { + return renderer; + } + IStackPositioner positioner = RecipeInfo.getStackPositioner( gui, "crafting2x2" ); + if ( positioner == null ) + return null; + return new DefaultOverlayRenderer( getIngredientStacks( recipe ), positioner ); + } + + @Override + public IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe) + { + IOverlayHandler handler = super.getOverlayHandler( gui, recipe ); + if ( handler != null ) + { + return handler; + } + return RecipeInfo.getOverlayHandler( gui, "crafting2x2" ); + } + + public boolean isRecipe2x2(int recipe) + { + for (PositionedStack stack : getIngredientStacks( recipe )) + { + if ( (stack.relx > 43) || (stack.rely > 24) ) + return false; + } + return true; + } + + public class CachedShapedRecipe extends TemplateRecipeHandler.CachedRecipe + { + + public ArrayList ingredients; + public PositionedStack result; + + public CachedShapedRecipe(AEShapedQuartzRecipe irecipe) { + result = new PositionedStack( irecipe.getRecipeOutput(), 119, 24 ); + ingredients = new ArrayList(); + setIngredients( irecipe.getWidth(), irecipe.getHeight(), irecipe.getIngredients() ); + } + + public void setIngredients(int width, int height, Object[] items) + { + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + if ( items[(y * width + x)] != null ) + { + PositionedStack stack = new PositionedStack( items[(y * width + x)], 25 + x * 18, 6 + y * 18, false ); + stack.setMaxSize( 1 ); + this.ingredients.add( stack ); + } + } + } + } + + @Override + public List getIngredients() + { + return getCycledIngredients( cycleticks / 20, this.ingredients ); + } + + @Override + public PositionedStack getResult() + { + return this.result; + } + + public void computeVisuals() + { + for (PositionedStack p : this.ingredients) + { + p.generatePermutations(); + } + this.result.generatePermutations(); + } + } +} \ No newline at end of file diff --git a/items/AEBaseItem.java b/items/AEBaseItem.java new file mode 100644 index 00000000..5ebe4df2 --- /dev/null +++ b/items/AEBaseItem.java @@ -0,0 +1,52 @@ +package appeng.items; + +import java.util.EnumSet; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class AEBaseItem extends Item implements IAEFeature +{ + + String FeatureFullname; + String FeatureSubname; + AEFeatureHandler feature; + + @Override + public String toString() + { + return FeatureFullname; + } + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public void setfeature(EnumSet f) + { + feature = new AEFeatureHandler( f, this, FeatureSubname ); + } + + public AEBaseItem(Class c) { + this( c, null ); + } + + public AEBaseItem(Class c, String subname) { + super( Configuration.instance.getItemID( c, subname ) ); + FeatureSubname = subname; + FeatureFullname = AEFeatureHandler.getName( c, subname ); + } + + @Override + public boolean isBookEnchantable(ItemStack itemstack1, ItemStack itemstack2) + { + return false; + } + +} diff --git a/items/ItemEncodedPattern.java b/items/ItemEncodedPattern.java new file mode 100644 index 00000000..832b0947 --- /dev/null +++ b/items/ItemEncodedPattern.java @@ -0,0 +1,25 @@ +package appeng.items; + +import java.util.EnumSet; + +import net.minecraft.item.ItemStack; +import appeng.api.crafting.ICraftingPatternMAC; +import appeng.api.implementations.ICraftingPatternItem; +import appeng.core.features.AEFeature; + +public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternItem +{ + + public ItemEncodedPattern() { + super( ItemEncodedPattern.class ); + setfeature( EnumSet.of( AEFeature.Crafting ) ); + } + + @Override + public ICraftingPatternMAC getPatternForItem(ItemStack is) + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/items/materials/ItemMaterial.java b/items/materials/ItemMaterial.java new file mode 100644 index 00000000..be8261dd --- /dev/null +++ b/items/materials/ItemMaterial.java @@ -0,0 +1,90 @@ +package appeng.items.materials; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.oredict.OreDictionary; +import appeng.api.implementations.IStorageComponent; +import appeng.items.AEBaseItem; + +public class ItemMaterial extends AEBaseItem implements IStorageComponent +{ + + final MaterialType material; + + public ItemMaterial(MaterialType type) { + super( ItemMaterial.class, type.name() ); + setfeature( type.getFeature() ); + material = type; + + if ( type.getOreName() != null ) + OreDictionary.registerOre( type.getOreName(), this ); + } + + @Override + public boolean hasCustomEntity(ItemStack is) + { + return material.hasCustomEntity(); + } + + @Override + public Entity createEntity(World w, Entity location, ItemStack itemstack) + { + Class droppedEntity = material.getCustomEntityClass(); + Entity eqi; + + try + { + eqi = droppedEntity.getConstructor( World.class, double.class, double.class, double.class, ItemStack.class ).newInstance( w, location.posX, + location.posY, location.posZ, itemstack ); + } + catch (Throwable t) + { + throw new RuntimeException( t ); + } + + eqi.motionX = location.motionX; + eqi.motionY = location.motionY; + eqi.motionZ = location.motionZ; + + if ( location instanceof EntityItem && eqi instanceof EntityItem ) + ((EntityItem) eqi).delayBeforeCanPickup = ((EntityItem) location).delayBeforeCanPickup; + + return eqi; + } + + @Override + public int getBytes(ItemStack is) + { + switch (material) + { + case Cell1kPart: + return 1024; + case Cell4kPart: + return 1024 * 4; + case Cell16kPart: + return 1024 * 16; + case Cell64kPart: + return 1024 * 64; + default: + } + return 0; + } + + @Override + public boolean isStorageComponent(ItemStack is) + { + switch (material) + { + case Cell1kPart: + case Cell4kPart: + case Cell16kPart: + case Cell64kPart: + return true; + default: + } + return false; + } + +} diff --git a/items/materials/MaterialType.java b/items/materials/MaterialType.java new file mode 100644 index 00000000..69e7b704 --- /dev/null +++ b/items/materials/MaterialType.java @@ -0,0 +1,97 @@ +package appeng.items.materials; + +import java.util.EnumSet; + +import net.minecraft.entity.Entity; +import net.minecraftforge.oredict.OreDictionary; +import appeng.client.render.entity.EntityIds; +import appeng.core.AppEng; +import appeng.core.features.AEFeature; +import appeng.entity.EntityChargedQuartz; +import appeng.entity.EntitySingularity; +import cpw.mods.fml.common.registry.EntityRegistry; + +public enum MaterialType +{ + CertusQuartzCrystal(AEFeature.Core), CertusQuartzCrystalCharged(AEFeature.Core, EntityChargedQuartz.class), + + CertusQuartzDust, NetherQuartzDust(AEFeature.Core, "dustNetherQuartz"), Flour(AEFeature.Flour, "dustWheat"), GoldDust(AEFeature.Core, "dustGold"), IronDust( + AEFeature.Core, "dustIron"), IronNugget(AEFeature.Core, "nuggetIron"), + + Silicon(AEFeature.Core, "itemSilicon"), MatterBall, + + FluixCrystal(AEFeature.Core, "crystalFLuix"), FluixDust(AEFeature.Core, "dustFluix"), FluixPearl(AEFeature.Core, "pearlFluix"), + + PureifiedCertusQuartzCrystal, PureifiedNetherQuartzCrystal, PureifiedFluixCrystal, + + LogicProcessorAsm(AEFeature.QuartzKnife), LogicProcessor, + + CalcProcessor, EngProcessor, + + // Basic Cards + BasicCard, CardRedstone, CardCapacity, + + // Adv Cards + AdvCard, CardFuzzy, CardSpeed, + + Cell2SpatialPart(AEFeature.SpatialIO), Cell16SpatialPart(AEFeature.SpatialIO), Cell128SpatialPart(AEFeature.SpatialIO), + + Cell1kPart(AEFeature.StorageCells), Cell4kPart(AEFeature.StorageCells), Cell16kPart(AEFeature.StorageCells), Cell64kPart(AEFeature.StorageCells), EmptyStorageCell( + AEFeature.StorageCells), + + WoodenGear(AEFeature.GrindStone, "gearWood"), + + Wireless(AEFeature.WirelessAccessTerminal), WirelessBooster(AEFeature.WirelessAccessTerminal), + + BlankPattern, FormationCore, AnnihilationCore, + + EnderDust(AEFeature.QuantumNetworkBridge, "dustEnder"), Singularity(AEFeature.QuantumNetworkBridge), QESingularity(AEFeature.QuantumNetworkBridge, + EntitySingularity.class); + + private String oreName; + private EnumSet features; + private Class droppedEntity; + + MaterialType() { + features = EnumSet.of( AEFeature.Core ); + } + + MaterialType(AEFeature part) { + features = EnumSet.of( part ); + } + + MaterialType(AEFeature part, Class c) { + features = EnumSet.of( part ); + droppedEntity = c; + + EntityRegistry.registerModEntity( droppedEntity, droppedEntity.getSimpleName(), EntityIds.get( droppedEntity ), AppEng.instance, 16, 4, true ); + } + + MaterialType(AEFeature part, String oreDictionary) { + features = EnumSet.of( part ); + oreName = oreDictionary; + if ( OreDictionary.getOres( oreDictionary ).size() > 0 ) + features.add( AEFeature.DuplicateItems ); + } + + public EnumSet getFeature() + { + return features; + } + + public String getOreName() + { + return oreName; + } + + public boolean hasCustomEntity() + { + return droppedEntity != null; + } + + public Class getCustomEntityClass() + { + return droppedEntity; + } + +} diff --git a/items/parts/ItemFacade.java b/items/parts/ItemFacade.java new file mode 100644 index 00000000..48e270ad --- /dev/null +++ b/items/parts/ItemFacade.java @@ -0,0 +1,167 @@ +package appeng.items.parts; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockGlass; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.block.solids.OreQuartz; +import appeng.client.render.BusRenderer; +import appeng.core.features.AEFeature; +import appeng.facade.FacadePart; +import appeng.facade.IFacadeItem; +import appeng.items.AEBaseItem; +import appeng.util.Platform; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ItemFacade extends AEBaseItem implements IFacadeItem +{ + + public ItemFacade() { + super( ItemFacade.class ); + setfeature( EnumSet.of( AEFeature.Facades ) ); + setHasSubtypes( true ); + if ( Platform.isClient() ) + MinecraftForgeClient.registerItemRenderer( this.itemID, BusRenderer.instance ); + } + + @Override + @SideOnly(Side.CLIENT) + public int getSpriteNumber() + { + return 0; + } + + @Override + public boolean onItemUse(ItemStack is, EntityPlayer player, World w, int x, int y, int z, int side, float hitX, float hitY, float hitZ) + { + return AEApi.instance().partHelper().placeBus( is, x, y, z, side, player, w ); + } + + @Override + public FacadePart createPartFromItemStack(ItemStack is, ForgeDirection side) + { + ItemStack in = getTextureItem( is ); + if ( in != null ) + return new FacadePart( is, side ); + return null; + } + + List subTypes = null; + + @Override + public void getSubItems(int number, CreativeTabs tab, List list) + { + calculateSubTypes(); + list.addAll( subTypes ); + } + + public ItemStack createFromInts(int[] ids) + { + ItemStack is = new ItemStack( AEApi.instance().items().itemFacade.item() ); + NBTTagCompound data = new NBTTagCompound(); + data.setIntArray( "x", ids ); + is.setTagCompound( data ); + return is; + } + + @Override + public ItemStack getTextureItem(ItemStack is) + { + Block blk = getBlock( is ); + if ( blk != null ) + return new ItemStack( blk, 1, getMeta( is ) ); + return null; + } + + private void calculateSubTypes() + { + if ( subTypes == null ) + { + subTypes = new ArrayList(); + for (Block b : Block.blocksList) + { + if ( b != null && (b.isOpaqueCube() && !b.getTickRandomly() && !(b instanceof OreQuartz)) || b instanceof BlockGlass ) + { + try + { + List tmpList = new ArrayList(); + b.getSubBlocks( b.blockID, b.getCreativeTabToDisplayOn(), tmpList ); + for (ItemStack l : tmpList) + { + ItemStack is = new ItemStack( this ); + NBTTagCompound data = new NBTTagCompound(); + int[] ds = new int[2]; + ds[0] = l.itemID; + ds[1] = l.getItem().getMetadata( l.getItemDamage() ); + data.setIntArray( "x", ds ); + is.setTagCompound( data ); + + subTypes.add( is ); + } + } + catch (Throwable t) + { + // just absorb.. + } + } + } + } + } + + @Override + public Block getBlock(ItemStack is) + { + NBTTagCompound data = is.getTagCompound(); + if ( data != null ) + { + int[] blk = data.getIntArray( "x" ); + if ( blk != null && blk.length == 2 ) + return Block.blocksList[blk[0]]; + } + return Block.glass; + } + + @Override + public int getMeta(ItemStack is) + { + NBTTagCompound data = is.getTagCompound(); + if ( data != null ) + { + int[] blk = data.getIntArray( "x" ); + if ( blk != null && blk.length == 2 ) + return blk[1]; + } + return 0; + } + + @Override + public String getItemDisplayName(ItemStack is) + { + try + { + ItemStack in = getTextureItem( is ); + if ( in != null ) + { + return super.getItemDisplayName( is ) + " - " + in.getDisplayName(); + } + } + catch (Throwable t) + { + + } + + return super.getItemDisplayName( is ); + } + +} diff --git a/items/parts/ItemPart.java b/items/parts/ItemPart.java new file mode 100644 index 00000000..3f871012 --- /dev/null +++ b/items/parts/ItemPart.java @@ -0,0 +1,73 @@ +package appeng.items.parts; + +import java.util.List; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.api.parts.IPartItem; +import appeng.api.parts.IPart; +import appeng.items.AEBaseItem; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ItemPart extends AEBaseItem implements IPartItem +{ + + final PartType part; + + public ItemPart(PartType type) { + super( ItemPart.class, type.name() ); + setfeature( type.getFeature() ); + AEApi.instance().partHelper().setItemBusRenderer( this ); + part = type; + if ( type == PartType.CableSmart || type == PartType.CableCovered || type == PartType.CableGlass ) + { + setHasSubtypes( true ); + } + } + + @Override + @SideOnly(Side.CLIENT) + public int getSpriteNumber() + { + return 0; + } + + @Override + public boolean onItemUse(ItemStack is, EntityPlayer player, World w, int x, int y, int z, int side, float hitX, float hitY, + float hitZ) + { + return AEApi.instance().partHelper().placeBus( is, x, y, z, side, player, w ); + } + + @Override + public IPart createPartFromItemStack(ItemStack is) + { + try + { + return part.getPart().getConstructor( ItemStack.class ).newInstance( is ); + } + catch (Throwable e) + { + throw new RuntimeException( "Unable to construct IBusPart from IBusItem : " + part.getPart().getName() + + " ; Possibly didn't have correct constructor( ItemStack )", e ); + } + } + + @Override + public void getSubItems(int number, CreativeTabs tab, List list) + { + if ( part == PartType.CableSmart || part == PartType.CableCovered || part == PartType.CableGlass ) + { + list.add( new ItemStack( this, 1, 16 ) ); + for (int x = 0; x < 16; x++) + list.add( new ItemStack( this, 1, x ) ); + return; + } + super.getSubItems( number, tab, list ); + } + +} diff --git a/items/parts/PartType.java b/items/parts/PartType.java new file mode 100644 index 00000000..ea48982f --- /dev/null +++ b/items/parts/PartType.java @@ -0,0 +1,93 @@ +package appeng.items.parts; + +import java.util.EnumSet; + +import appeng.api.parts.IPart; +import appeng.core.features.AEFeature; +import appeng.parts.automation.PartAnnihilationPlane; +import appeng.parts.automation.PartExportBus; +import appeng.parts.automation.PartFormationPlane; +import appeng.parts.automation.PartImportBus; +import appeng.parts.automation.PartLevelEmitter; +import appeng.parts.misc.PartCableAnchor; +import appeng.parts.misc.PartInvertedToggleBus; +import appeng.parts.misc.PartP2PTunnel; +import appeng.parts.misc.PartStorageBus; +import appeng.parts.misc.PartToggleBus; +import appeng.parts.networking.PartCableCovered; +import appeng.parts.networking.PartCableGlass; +import appeng.parts.networking.PartCableSmart; +import appeng.parts.networking.PartQuartzFiber; +import appeng.parts.reporting.PartConversionMonitor; +import appeng.parts.reporting.PartCraftingMonitor; +import appeng.parts.reporting.PartCraftingTerminal; +import appeng.parts.reporting.PartDarkMonitor; +import appeng.parts.reporting.PartMonitor; +import appeng.parts.reporting.PartPatternTerminal; +import appeng.parts.reporting.PartSemiDarkMonitor; +import appeng.parts.reporting.PartStorageMonitor; +import appeng.parts.reporting.PartTerminal; + +public enum PartType +{ + ToggleBus(AEFeature.Core, PartToggleBus.class), + + InvertedToggleBus(AEFeature.Core, PartInvertedToggleBus.class), + + CableSmart(AEFeature.Core, PartCableSmart.class), CableCovered(AEFeature.Core, PartCableCovered.class), CableGlass(AEFeature.Core, PartCableGlass.class), + + CableAnchor(AEFeature.Core, PartCableAnchor.class), + + QuartzFiber(AEFeature.Core, PartQuartzFiber.class), + + Monitior(AEFeature.Core, PartMonitor.class), + + SemiDarkMonitor(AEFeature.Core, PartSemiDarkMonitor.class), + + DarkMonitor(AEFeature.Core, PartDarkMonitor.class), + + StorageBus(AEFeature.StorageBus, PartStorageBus.class), + + ImportBus(AEFeature.ImportBus, PartImportBus.class), + + ExportBus(AEFeature.ExportBus, PartExportBus.class), + + LevelEmitter(AEFeature.LevelEmiter, PartLevelEmitter.class), + + AnnihilationPlane(AEFeature.AnnihilationPlane, PartAnnihilationPlane.class), + + FormationPlane(AEFeature.FormationPlane, PartFormationPlane.class), + + P2PTunnel(AEFeature.P2PTunnel, PartP2PTunnel.class), + + CraftingMonitor(AEFeature.Crafting, PartCraftingMonitor.class), + + PatternTerminal(AEFeature.CraftingTerminal, PartPatternTerminal.class), + + CraftingTerminal(AEFeature.CraftingTerminal, PartCraftingTerminal.class), + + Terminal(AEFeature.Core, PartTerminal.class), + + StorageMonitor(AEFeature.StorageMonitor, PartStorageMonitor.class), + + ConversionMonitor(AEFeature.PartConversionMonitor, PartConversionMonitor.class); + + private EnumSet features; + private Class myPart; + + PartType(AEFeature part, Class c) { + features = EnumSet.of( part ); + myPart = c; + } + + public EnumSet getFeature() + { + return features; + } + + public Class getPart() + { + return myPart; + } + +} diff --git a/items/storage/ItemBasicStorageCell.java b/items/storage/ItemBasicStorageCell.java new file mode 100644 index 00000000..2d42d4c0 --- /dev/null +++ b/items/storage/ItemBasicStorageCell.java @@ -0,0 +1,119 @@ +package appeng.items.storage; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; +import appeng.api.implementations.IStorageCell; +import appeng.api.storage.data.IAEItemStack; +import appeng.core.features.AEFeature; +import appeng.items.AEBaseItem; +import appeng.items.materials.MaterialType; +import appeng.me.storage.CellInventory; +import appeng.me.storage.CellInventoryHandler; + +public class ItemBasicStorageCell extends AEBaseItem implements IStorageCell +{ + + final MaterialType component; + final int totalBytes; + final double idleDrain; + + public ItemBasicStorageCell(MaterialType whichCell, int Kilobytes) { + super( ItemBasicStorageCell.class, Kilobytes + "k" ); + setfeature( EnumSet.of( AEFeature.StorageCells ) ); + maxStackSize = 1; + totalBytes = Kilobytes * 1024; + component = whichCell; + + switch (component) + { + case Cell1kPart: + idleDrain = 0.5; + break; + case Cell4kPart: + idleDrain = 1.0; + break; + case Cell16kPart: + idleDrain = 1.5; + break; + case Cell64kPart: + idleDrain = 2.0; + break; + default: + idleDrain = 0.0; + } + } + + @Override + public void addInformation(ItemStack i, EntityPlayer p, List l, boolean b) + { + CellInventory cd = ((CellInventoryHandler) CellInventory.getCell( i )).getCellInv(); + + if ( cd != null ) + { + l.add( cd.usedBytes() + " " + StatCollector.translateToLocal( "Appeng.GuiITooltip.Of" ) + " " + cd.totalBytes() + " " + + StatCollector.translateToLocal( "Appeng.GuiITooltip.BytesUsed" ) ); + l.add( cd.storedItemTypes() + " " + StatCollector.translateToLocal( "Appeng.GuiITooltip.Of" ) + " " + cd.getTotalItemTypes() + " " + + StatCollector.translateToLocal( "Appeng.GuiITooltip.Types" ) ); + /* + * if ( cd.isPreformatted() ) { String List = StatCollector.translateToLocal( cd.getListMode() == + * ListMode.WHITELIST ? "AppEng.Gui.Whitelisted" : "AppEng.Gui.Blacklisted" ); if ( cd.isFuzzyPreformatted() + * ) l.add( StatCollector.translateToLocal( "Appeng.GuiITooltip.Partitioned" ) + " - " + List + " " + + * StatCollector.translateToLocal( "Appeng.GuiITooltip.Fuzzy" ) ); else l.add( + * StatCollector.translateToLocal( "Appeng.GuiITooltip.Partitioned" ) + " - " + List + " " + + * StatCollector.translateToLocal( "Appeng.GuiITooltip.Precise" ) ); } + */ + } + } + + @Override + public int getBytes(ItemStack cellItem) + { + return totalBytes; + } + + @Override + public int BytePerType(ItemStack iscellItem) + { + return 8; + } + + @Override + public int getTotalTypes(ItemStack cellItem) + { + return 63; + } + + @Override + public boolean isBlackListed(ItemStack cellItem, IAEItemStack requsetedAddition) + { + Item i = requsetedAddition.getItem(); + + if ( i instanceof IStorageCell ) + return !((IStorageCell) i).storableInStorageCell(); + + return false; + } + + @Override + public boolean storableInStorageCell() + { + return false; + } + + @Override + public boolean isStorageCell(ItemStack i) + { + return true; + } + + @Override + public double getIdleDrain() + { + return idleDrain; + } +} diff --git a/items/storage/ItemCreativeStorageCell.java b/items/storage/ItemCreativeStorageCell.java new file mode 100644 index 00000000..0851c24b --- /dev/null +++ b/items/storage/ItemCreativeStorageCell.java @@ -0,0 +1,17 @@ +package appeng.items.storage; + +import java.util.EnumSet; + +import appeng.core.features.AEFeature; +import appeng.items.AEBaseItem; + +public class ItemCreativeStorageCell extends AEBaseItem +{ + + public ItemCreativeStorageCell() { + super( ItemCreativeStorageCell.class ); + setfeature( EnumSet.of( AEFeature.StorageCells, AEFeature.Creative ) ); + maxStackSize = 1; + } + +} diff --git a/items/storage/ItemSpatialStorageCell.java b/items/storage/ItemSpatialStorageCell.java new file mode 100644 index 00000000..ce60f96e --- /dev/null +++ b/items/storage/ItemSpatialStorageCell.java @@ -0,0 +1,21 @@ +package appeng.items.storage; + +import java.util.EnumSet; + +import appeng.core.features.AEFeature; +import appeng.items.AEBaseItem; +import appeng.items.materials.MaterialType; + +public class ItemSpatialStorageCell extends AEBaseItem +{ + final MaterialType component; + final int maxRegion; + + public ItemSpatialStorageCell(MaterialType whichCell, int spatialScale) { + super( ItemSpatialStorageCell.class, spatialScale + "Cubed" ); + setfeature( EnumSet.of( AEFeature.SpatialIO ) ); + maxRegion = spatialScale; + component = whichCell; + } + +} diff --git a/items/tools/ToolMemoryCard.java b/items/tools/ToolMemoryCard.java new file mode 100644 index 00000000..965ad630 --- /dev/null +++ b/items/tools/ToolMemoryCard.java @@ -0,0 +1,82 @@ +package appeng.items.tools; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; +import appeng.api.implementations.IMemoryCard; +import appeng.api.implementations.MemoryCardMessages; +import appeng.core.features.AEFeature; +import appeng.core.localization.PlayerMessages; +import appeng.items.AEBaseItem; +import appeng.util.Platform; + +public class ToolMemoryCard extends AEBaseItem implements IMemoryCard +{ + + public ToolMemoryCard() { + super( ToolMemoryCard.class ); + setfeature( EnumSet.of( AEFeature.Core ) ); + } + + @Override + public void addInformation(ItemStack i, EntityPlayer p, List l, boolean b) + { + l.add( StatCollector.translateToLocal( getSettingsName( i ) ) ); + NBTTagCompound data = getData( i ); + if ( data.hasKey( "tooltip" ) ) + { + l.add( StatCollector.translateToLocal( data.getString( "tooltip" ) ) ); + } + } + + @Override + public void setMemoryCardContents(ItemStack is, String SettingsName, NBTTagCompound data) + { + NBTTagCompound c = Platform.openNbtData( is ); + c.setString( "Config", SettingsName ); + ; + c.setCompoundTag( "Data", data ); + } + + @Override + public String getSettingsName(ItemStack is) + { + NBTTagCompound c = Platform.openNbtData( is ); + String name = c.getString( "Config" ); + return name == null || name == "" ? "gui.appliedenergistics2.Blank" : name; + } + + @Override + public NBTTagCompound getData(ItemStack is) + { + NBTTagCompound c = Platform.openNbtData( is ); + NBTTagCompound o = c.getCompoundTag( "Data" ); + if ( o == null ) + o = new NBTTagCompound(); + return (NBTTagCompound) o.copy(); + } + + @Override + public void notifyUser(Block blk, EntityPlayer player, MemoryCardMessages msg) + { + switch (msg) + { + case INVALID_MACHINE: + player.sendChatToPlayer( PlayerMessages.InvalidMachine.get() ); + break; + case SETTINGS_LOADED: + player.sendChatToPlayer( PlayerMessages.LoadedSettings.get() ); + break; + case SETTINGS_SAVED: + player.sendChatToPlayer( PlayerMessages.SavedSettings.get() ); + break; + default: + } + } + +} diff --git a/items/tools/powered/ToolChargedStaff.java b/items/tools/powered/ToolChargedStaff.java new file mode 100644 index 00000000..9de6494d --- /dev/null +++ b/items/tools/powered/ToolChargedStaff.java @@ -0,0 +1,53 @@ +package appeng.items.tools.powered; + +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import appeng.core.features.AEFeature; +import appeng.core.sync.packets.PacketLightning; +import appeng.items.tools.powered.powersink.AEBasePoweredItem; +import appeng.server.ServerHelper; +import appeng.util.Platform; + +public class ToolChargedStaff extends AEBasePoweredItem +{ + + public ToolChargedStaff() { + super( ToolChargedStaff.class, null ); + setfeature( EnumSet.of( AEFeature.ChargedStaff, AEFeature.PoweredTools ) ); + maxStoredPower = 8000; + } + + @Override + public boolean hitEntity(ItemStack item, EntityLivingBase target, EntityLivingBase hitter) + { + if ( this.getAECurrentPower( item ) > 300 ) + { + extractAEPower( item, 300 ); + if ( Platform.isServer() ) + { + try + { + for (int x = 0; x < 2; x++) + { + float dx = (float) (Platform.getRandomFloat() * target.width + target.boundingBox.minX); + float dy = (float) (Platform.getRandomFloat() * target.height + target.boundingBox.minY); + float dz = (float) (Platform.getRandomFloat() * target.width + target.boundingBox.minZ); + ServerHelper.proxy.sendToAllNearExcept( null, dx, dy, dz, 32.0, target.worldObj, (new PacketLightning( dx, dy, dz )).getPacket() ); + } + } + catch (IOException e) + { + + } + } + target.attackEntityFrom( DamageSource.magic, 6 ); + return true; + } + + return false; + } +} diff --git a/items/tools/powered/ToolEntropyManipulator.java b/items/tools/powered/ToolEntropyManipulator.java new file mode 100644 index 00000000..b5addec9 --- /dev/null +++ b/items/tools/powered/ToolEntropyManipulator.java @@ -0,0 +1,268 @@ +package appeng.items.tools.powered; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Hashtable; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.util.EnumMovingObjectType; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.core.features.AEFeature; +import appeng.items.tools.powered.powersink.AEBasePoweredItem; +import appeng.util.InWorldToolOperationResult; +import appeng.util.Platform; + +public class ToolEntropyManipulator extends AEBasePoweredItem +{ + + static private Hashtable heatUp; + static private Hashtable coolDown; + + static public void heat(int BlockID, int Metadata, World w, int x, int y, int z) + { + InWorldToolOperationResult r = heatUp.get( BlockID + ":" + Metadata ); + + if ( r == null ) + { + r = heatUp.get( BlockID + ":*" ); + } + + if ( r.BlockItem != null ) + { + w.setBlock( x, y, z, r.BlockItem.itemID, r.BlockItem.getItemDamage(), 3 ); + } + else + { + w.setBlock( x, y, z, 0, 0, 3 ); + } + + if ( r.Drops != null ) + { + Platform.spawnDrops( w, x, y, z, r.Drops ); + } + } + + static public boolean canHeat(int BlockID, int Metadata) + { + InWorldToolOperationResult r = heatUp.get( BlockID + ":" + Metadata ); + + if ( r == null ) + { + r = heatUp.get( BlockID + ":*" ); + } + + return r != null; + } + + static public void cool(int BlockID, int Metadata, World w, int x, int y, int z) + { + InWorldToolOperationResult r = coolDown.get( BlockID + ":" + Metadata ); + + if ( r == null ) + { + r = coolDown.get( BlockID + ":*" ); + } + + if ( r.BlockItem != null ) + { + w.setBlock( x, y, z, r.BlockItem.itemID, r.BlockItem.getItemDamage(), 3 ); + } + else + { + w.setBlock( x, y, z, 0, 0, 3 ); + } + + if ( r.Drops != null ) + { + Platform.spawnDrops( w, x, y, z, r.Drops ); + } + } + + static public boolean canCool(int BlockID, int Metadata) + { + InWorldToolOperationResult r = coolDown.get( BlockID + ":" + Metadata ); + + if ( r == null ) + { + r = coolDown.get( BlockID + ":*" ); + } + + return r != null; + } + + public ToolEntropyManipulator() { + super( ToolEntropyManipulator.class, null ); + setfeature( EnumSet.of( AEFeature.EntropyManipulator, AEFeature.PoweredTools ) ); + + coolDown = new Hashtable(); + coolDown.put( Block.stone.blockID + ":0", new InWorldToolOperationResult( new ItemStack( Block.cobblestone ) ) ); + coolDown.put( Block.stoneBrick.blockID + ":0", new InWorldToolOperationResult( new ItemStack( Block.stoneBrick, 1, 2 ) ) ); + coolDown.put( Block.lavaStill.blockID + ":*", new InWorldToolOperationResult( new ItemStack( Block.obsidian ) ) ); + coolDown.put( Block.lavaMoving.blockID + ":*", new InWorldToolOperationResult( new ItemStack( Block.obsidian ) ) ); + coolDown.put( Block.grass.blockID + ":*", new InWorldToolOperationResult( new ItemStack( Block.dirt ) ) ); + + List snowBalls = new ArrayList(); + snowBalls.add( new ItemStack( Item.snowball ) ); + coolDown.put( Block.waterMoving.blockID + ":*", new InWorldToolOperationResult( null, snowBalls ) ); + coolDown.put( Block.waterStill.blockID + ":*", new InWorldToolOperationResult( new ItemStack( Block.ice ) ) ); + + heatUp = new Hashtable(); + heatUp.put( Block.ice.blockID + ":0", new InWorldToolOperationResult( new ItemStack( Block.waterStill ) ) ); + heatUp.put( Block.waterMoving.blockID + ":*", new InWorldToolOperationResult() ); + heatUp.put( Block.waterStill.blockID + ":*", new InWorldToolOperationResult() ); + heatUp.put( Block.blockSnow.blockID + ":*", new InWorldToolOperationResult( new ItemStack( Block.waterStill ) ) ); + } + + @Override + public boolean hitEntity(ItemStack item, EntityLivingBase target, EntityLivingBase hitter) + { + if ( this.getAECurrentPower( item ) > 1600 ) + { + extractAEPower( item, 1600 ); + target.setFire( 8 ); + } + + return false; + } + + @Override + public ItemStack onItemRightClick(ItemStack item, World w, EntityPlayer p) + { + MovingObjectPosition target = this.getMovingObjectPositionFromPlayer( w, p, true ); + + if ( target == null ) + return item; + else + { + if ( target.typeOfHit == EnumMovingObjectType.TILE ) + { + int x = target.blockX; + int y = target.blockY; + int z = target.blockZ; + + if ( w.getBlockMaterial( x, y, z ) == Material.lava || w.getBlockMaterial( x, y, z ) == Material.water ) + { + if ( w.canMineBlock( p, x, y, z ) ) + { + onItemUse( item, p, w, x, y, z, 0, 0.0F, 0.0F, 0.0F ); + } + } + } + } + + return item; + } + + @Override + public boolean onItemUse(ItemStack item, EntityPlayer p, World w, int x, int y, int z, int side, float hitX, float hitY, float hitZ) + { + if ( this.getAECurrentPower( item ) > 1600 ) + { + if ( !p.canPlayerEdit( x, y, z, side, item ) ) + return false; + + int BlockID = w.getBlockId( x, y, z ); + int Metadata = w.getBlockMetadata( x, y, z ); + + if ( p.isSneaking() ) + { + if ( canCool( BlockID, Metadata ) ) + { + extractAEPower( item, 1600 ); + cool( BlockID, Metadata, w, x, y, z ); + return true; + } + } + else + { + if ( canHeat( BlockID, Metadata ) ) + { + extractAEPower( item, 1600 ); + heat( BlockID, Metadata, w, x, y, z ); + return true; + } + + ItemStack[] stack = Platform.getBlockDrops( w, x, y, z ); + List out = new ArrayList(); + boolean hasFurnaceable = false; + boolean canFurnaceable = true; + + for (ItemStack i : stack) + { + ItemStack result = FurnaceRecipes.smelting().getSmeltingResult( i ); + + if ( result != null ) + { + if ( result.getItem() instanceof ItemBlock ) + { + if ( ((ItemBlock) result.getItem()).getBlockID() == BlockID && result.getItem().getDamage( result ) == Metadata ) + { + canFurnaceable = false; + } + } + hasFurnaceable = true; + out.add( result ); + } + else + { + canFurnaceable = false; + out.add( i ); + } + } + + if ( hasFurnaceable && canFurnaceable ) + { + extractAEPower( item, 1600 ); + InWorldToolOperationResult or = InWorldToolOperationResult.getBlockOperationResult( out.toArray( new ItemStack[out.size()] ) ); + w.playSoundEffect( (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F ); + + if ( or.BlockItem == null ) + { + w.setBlock( x, y, z, 0, 0, 3 ); + } + else + { + w.setBlock( x, y, z, or.BlockItem.itemID, or.BlockItem.getItemDamage(), 3 ); + } + + if ( or.Drops != null ) + { + Platform.spawnDrops( w, x, y, z, or.Drops ); + } + + return true; + } + else + { + ForgeDirection dir = ForgeDirection.getOrientation( side ); + x += dir.offsetX; + y += dir.offsetY; + z += dir.offsetZ; + + if ( !p.canPlayerEdit( x, y, z, side, item ) ) + return false; + + if ( w.isAirBlock( x, y, z ) ) + { + w.playSoundEffect( (double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D, "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F ); + w.setBlock( x, y, z, Block.fire.blockID ); + } + + return true; + } + } + } + + return false; + } +} diff --git a/items/tools/powered/ToolMassCannon.java b/items/tools/powered/ToolMassCannon.java new file mode 100644 index 00000000..0da6709e --- /dev/null +++ b/items/tools/powered/ToolMassCannon.java @@ -0,0 +1,16 @@ +package appeng.items.tools.powered; + +import java.util.EnumSet; + +import appeng.core.features.AEFeature; +import appeng.items.tools.powered.powersink.AEBasePoweredItem; + +public class ToolMassCannon extends AEBasePoweredItem +{ + + public ToolMassCannon() { + super( ToolMassCannon.class, null ); + setfeature( EnumSet.of( AEFeature.MatterCannon, AEFeature.PoweredTools ) ); + } + +} diff --git a/items/tools/powered/ToolWirelessTerminal.java b/items/tools/powered/ToolWirelessTerminal.java new file mode 100644 index 00000000..c276d761 --- /dev/null +++ b/items/tools/powered/ToolWirelessTerminal.java @@ -0,0 +1,54 @@ +package appeng.items.tools.powered; + +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.core.features.AEFeature; +import appeng.items.tools.powered.powersink.AEBasePoweredItem; +import appeng.util.Platform; + +public class ToolWirelessTerminal extends AEBasePoweredItem +{ + + String name; + int DISTNACE_CALC = 2; + + public ToolWirelessTerminal() { + super( ToolWirelessTerminal.class, null ); + setfeature( EnumSet.of( AEFeature.WirelessAccessTerminal, AEFeature.PoweredTools ) ); + } + + @Override + public ItemStack onItemRightClick(ItemStack item, World w, EntityPlayer player) + { + AEApi.instance().registries().wireless().OpenWirelessTermainlGui( item, w, player ); + return item; + } + + @Override + public void addInformation(ItemStack i, EntityPlayer p, List l, boolean b) + { + if ( i.hasTagCompound() ) + { + NBTTagCompound tag = Platform.openNbtData( i ); + if ( tag != null ) + { + String encKey = tag.getString( "encKey" ); + + if ( encKey == null || encKey == "" ) + l.add( StatCollector.translateToLocal( "AppEng.GuiITooltip.Unlinked" ) ); + else + l.add( StatCollector.translateToLocal( "AppEng.GuiITooltip.Linked" ) ); + } + } + else + l.add( StatCollector.translateToLocal( "AppEng.GuiITooltip.Unlinked" ) ); + } + +} diff --git a/items/tools/powered/powersink/AEBasePoweredItem.java b/items/tools/powered/powersink/AEBasePoweredItem.java new file mode 100644 index 00000000..885e23d7 --- /dev/null +++ b/items/tools/powered/powersink/AEBasePoweredItem.java @@ -0,0 +1,10 @@ +package appeng.items.tools.powered.powersink; + +public class AEBasePoweredItem extends UniversalElectricity +{ + + public AEBasePoweredItem(Class c, String subname) { + super( c, subname ); + } + +} diff --git a/items/tools/powered/powersink/AERootPoweredItem.java b/items/tools/powered/powersink/AERootPoweredItem.java new file mode 100644 index 00000000..f476ecf4 --- /dev/null +++ b/items/tools/powered/powersink/AERootPoweredItem.java @@ -0,0 +1,179 @@ +package appeng.items.tools.powered.powersink; + +import java.text.MessageFormat; +import java.util.List; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.config.AccessRestriction; +import appeng.api.config.PowerUnits; +import appeng.api.implementations.IAEItemPowerStorage; +import appeng.items.AEBaseItem; +import appeng.util.Platform; + +public class AERootPoweredItem extends AEBaseItem implements IAEItemPowerStorage +{ + + private enum batteryOperation + { + STORAGE, INJECT, EXTRACT + }; + + public double maxStoredPower = 200000; + + public AERootPoweredItem(Class c, String subname) { + super( c, subname ); + setMaxDamage( 32 ); + hasSubtypes = false; + } + + @Override + public void addInformation(ItemStack is, EntityPlayer player, List lines, boolean advancedItemTooltips) + { + NBTTagCompound tag = is.getTagCompound(); + double internalCurrentPower = 0; + double internalMaxPower = getAEMaxPower( is ); + + if ( tag != null ) + { + internalCurrentPower = tag.getDouble( "internalCurrentPower" ); + } + + double percent = internalCurrentPower / internalMaxPower; + + lines.add( Platform.gui_localize( "Stored Energy" ) + ":" + MessageFormat.format( " {0,number,#} ", internalCurrentPower ) + + Platform.gui_localize( PowerUnits.AE.unlocalizedName ) + " - " + MessageFormat.format( " {0,number,#.##%} ", percent ) ); + + } + + @Override + public boolean isDamageable() + { + return true; + } + + @Override + public boolean isDamaged(ItemStack stack) + { + return true; + } + + @Override + public boolean isRepairable() + { + return false; + } + + @Override + public void setDamage(ItemStack stack, int damage) + { + + } + + final String EnergyVar = "internalCurrentPower"; + + private double getInternalBattery(ItemStack is, batteryOperation op, double adjustment) + { + NBTTagCompound data = Platform.openNbtData( is ); + + double currentStorage = data.getDouble( EnergyVar ); + double maxStorage = getAEMaxPower( is ); + + switch (op) + { + case INJECT: + currentStorage += adjustment; + if ( currentStorage > maxStorage ) + { + double diff = currentStorage - maxStorage; + data.setDouble( EnergyVar, maxStorage ); + return diff; + } + data.setDouble( EnergyVar, currentStorage ); + return 0; + case EXTRACT: + if ( currentStorage > adjustment ) + { + currentStorage -= adjustment; + data.setDouble( EnergyVar, currentStorage ); + return adjustment; + } + data.setDouble( EnergyVar, 0 ); + return currentStorage; + default: + break; + } + + return currentStorage; + } + + /** + * inject external + */ + double injectExternalPower(PowerUnits input, ItemStack is, double amount, boolean simulate) + { + if ( simulate ) + { + int requiredEU = (int) PowerUnits.AE.convertTo( PowerUnits.EU, getAEMaxPower( is ) - getAECurrentPower( is ) ); + if ( amount < requiredEU ) + return 0; + return amount - requiredEU; + } + else + { + double powerRemainder = injectAEPower( is, PowerUnits.EU.convertTo( PowerUnits.AE, amount ) ); + return PowerUnits.AE.convertTo( PowerUnits.EU, powerRemainder ); + } + } + + @Override + public double injectAEPower(ItemStack is, double amt) + { + return getInternalBattery( is, batteryOperation.INJECT, amt ); + } + + @Override + public double extractAEPower(ItemStack is, double amt) + { + return getInternalBattery( is, batteryOperation.EXTRACT, amt ); + } + + @Override + public double getAEMaxPower(ItemStack is) + { + return maxStoredPower; + } + + @Override + public double getAECurrentPower(ItemStack is) + { + return getInternalBattery( is, batteryOperation.STORAGE, 0 ); + } + + @Override + public AccessRestriction getPowerFlow(ItemStack is) + { + return AccessRestriction.WRITE; + } + + @Override + public int getDisplayDamage(ItemStack is) + { + return 32 - (int) (32 * (getAECurrentPower( is ) / getAEMaxPower( is ))); + } + + @Override + public void getSubItems(int id, CreativeTabs tab, List list) + { + super.getSubItems( id, tab, list ); + + ItemStack charged = new ItemStack( this, 1 ); + NBTTagCompound tag = Platform.openNbtData( charged ); + tag.setDouble( "internalCurrentPower", getAEMaxPower( charged ) ); + tag.setDouble( "internalMaxPower", getAEMaxPower( charged ) ); + list.add( charged ); + } + +} diff --git a/items/tools/powered/powersink/IC2.java b/items/tools/powered/powersink/IC2.java new file mode 100644 index 00000000..b58d2d53 --- /dev/null +++ b/items/tools/powered/powersink/IC2.java @@ -0,0 +1,63 @@ +package appeng.items.tools.powered.powersink; + +import ic2.api.item.IElectricItemManager; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import appeng.api.config.PowerUnits; + +public class IC2 extends AERootPoweredItem implements IElectricItemManager +{ + + public IC2(Class c, String subname) { + super( c, subname ); + } + + @Override + public int charge(ItemStack is, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) + { + return amount - ((int) injectExternalPower( PowerUnits.EU, is, amount, simulate )); + } + + @Override + public int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) + { + return 0; + } + + @Override + public int getCharge(ItemStack is) + { + return (int) PowerUnits.AE.convertTo( PowerUnits.EU, getAECurrentPower( is ) ); + } + + @Override + public boolean canUse(ItemStack is, int amount) + { + return getCharge( is ) > amount; + } + + @Override + public boolean use(ItemStack is, int amount, EntityLivingBase entity) + { + if ( canUse( is, amount ) ) + { + // use the power.. + extractAEPower( is, PowerUnits.EU.convertTo( PowerUnits.AE, amount ) ); + return true; + } + return false; + } + + @Override + public void chargeFromArmor(ItemStack itemStack, EntityLivingBase entity) + { + // wtf? + } + + @Override + public String getToolTip(ItemStack itemStack) + { + return null; + } + +} diff --git a/items/tools/powered/powersink/ThermalExpansion.java b/items/tools/powered/powersink/ThermalExpansion.java new file mode 100644 index 00000000..dda17104 --- /dev/null +++ b/items/tools/powered/powersink/ThermalExpansion.java @@ -0,0 +1,38 @@ +package appeng.items.tools.powered.powersink; + +import net.minecraft.item.ItemStack; +import appeng.api.config.PowerUnits; +import cofh.api.energy.IEnergyContainerItem; + +public class ThermalExpansion extends IC2 implements IEnergyContainerItem +{ + + public ThermalExpansion(Class c, String subname) { + super( c, subname ); + } + + @Override + public int receiveEnergy(ItemStack is, int maxReceive, boolean simulate) + { + return maxReceive - (int) injectExternalPower( PowerUnits.RF, is, maxReceive, simulate ); + } + + @Override + public int extractEnergy(ItemStack container, int maxExtract, boolean simulate) + { + return 0; + } + + @Override + public int getEnergyStored(ItemStack is) + { + return (int) PowerUnits.AE.convertTo( PowerUnits.RF, getAECurrentPower( is ) ); + } + + @Override + public int getMaxEnergyStored(ItemStack is) + { + return (int) PowerUnits.AE.convertTo( PowerUnits.EU, getMaxEnergyStored( is ) ); + } + +} diff --git a/items/tools/powered/powersink/UniversalElectricity.java b/items/tools/powered/powersink/UniversalElectricity.java new file mode 100644 index 00000000..408199ca --- /dev/null +++ b/items/tools/powered/powersink/UniversalElectricity.java @@ -0,0 +1,61 @@ +package appeng.items.tools.powered.powersink; + +import net.minecraft.item.ItemStack; +import universalelectricity.core.item.IItemElectric; +import appeng.api.config.PowerUnits; + +public class UniversalElectricity extends ThermalExpansion implements IItemElectric +{ + + public UniversalElectricity(Class c, String subname) { + super( c, subname ); + } + + @Override + public float recharge(ItemStack is, float energy, boolean doRecharge) + { + return (float) (energy - injectExternalPower( PowerUnits.KJ, is, energy, !doRecharge )); + } + + @Override + public float discharge(ItemStack is, float energy, boolean doDischarge) + { + return 0; + } + + @Override + public float getElectricityStored(ItemStack is) + { + return (int) PowerUnits.AE.convertTo( PowerUnits.KJ, getAECurrentPower( is ) ); + } + + @Override + public float getMaxElectricityStored(ItemStack is) + { + return (int) PowerUnits.AE.convertTo( PowerUnits.KJ, getAEMaxPower( is ) ); + } + + @Override + public void setElectricity(ItemStack is, float joules) + { + double currentPower = getAECurrentPower( is ); + double targetPower = PowerUnits.KJ.convertTo( PowerUnits.AE, joules ); + if ( targetPower > currentPower ) + injectAEPower( is, targetPower - currentPower ); + else + extractAEPower( is, currentPower - targetPower ); + } + + @Override + public float getTransfer(ItemStack is) + { + return (float) PowerUnits.AE.convertTo( PowerUnits.KJ, getAEMaxPower( is ) - getAECurrentPower( is ) ); + } + + @Override + public float getVoltage(ItemStack itemStack) + { + return 120; + } + +} diff --git a/items/tools/quartz/ToolQuartzAxe.java b/items/tools/quartz/ToolQuartzAxe.java new file mode 100644 index 00000000..f1531056 --- /dev/null +++ b/items/tools/quartz/ToolQuartzAxe.java @@ -0,0 +1,30 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.EnumToolMaterial; +import net.minecraft.item.ItemAxe; +import net.minecraftforge.common.MinecraftForge; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class ToolQuartzAxe extends ItemAxe implements IAEFeature +{ + + AEFeatureHandler feature; + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public ToolQuartzAxe(AEFeature Type) { + super( Configuration.instance.getItemID( ToolQuartzAxe.class, Type.name() ), EnumToolMaterial.IRON ); + MinecraftForge.setToolClass( this, "axe", EnumToolMaterial.IRON.getHarvestLevel() ); + feature = new AEFeatureHandler( EnumSet.of( Type, AEFeature.QuartzAxe ), this, Type.name() ); + } + +} diff --git a/items/tools/quartz/ToolQuartzCuttingKnife.java b/items/tools/quartz/ToolQuartzCuttingKnife.java new file mode 100644 index 00000000..0a1e074b --- /dev/null +++ b/items/tools/quartz/ToolQuartzCuttingKnife.java @@ -0,0 +1,44 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.ItemStack; +import appeng.core.features.AEFeature; +import appeng.items.AEBaseItem; + +public class ToolQuartzCuttingKnife extends AEBaseItem +{ + + public ToolQuartzCuttingKnife(AEFeature type) { + super( ToolQuartzCuttingKnife.class, type.name() ); + setfeature( EnumSet.of( type, AEFeature.QuartzKnife ) ); + setMaxDamage( 50 ); + setMaxStackSize( 1 ); + } + + @Override + public boolean isRepairable() + { + return false; + } + + @Override + public boolean doesContainerItemLeaveCraftingGrid(ItemStack par1ItemStack) + { + return false; + } + + @Override + public boolean hasContainerItem() + { + return true; + } + + @Override + public ItemStack getContainerItemStack(ItemStack itemStack) + { + itemStack.setItemDamage( itemStack.getItemDamage() + 1 ); + return itemStack; + } + +} diff --git a/items/tools/quartz/ToolQuartzHoe.java b/items/tools/quartz/ToolQuartzHoe.java new file mode 100644 index 00000000..04b68359 --- /dev/null +++ b/items/tools/quartz/ToolQuartzHoe.java @@ -0,0 +1,30 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.EnumToolMaterial; +import net.minecraft.item.ItemHoe; +import net.minecraftforge.common.MinecraftForge; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class ToolQuartzHoe extends ItemHoe implements IAEFeature +{ + + AEFeatureHandler feature; + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public ToolQuartzHoe(AEFeature Type) { + super( Configuration.instance.getItemID( ToolQuartzHoe.class, Type.name() ), EnumToolMaterial.IRON ); + MinecraftForge.setToolClass( this, "hoe", EnumToolMaterial.IRON.getHarvestLevel() ); + feature = new AEFeatureHandler( EnumSet.of( Type, AEFeature.QuartzHoe ), this, Type.name() ); + } + +} \ No newline at end of file diff --git a/items/tools/quartz/ToolQuartzPickaxe.java b/items/tools/quartz/ToolQuartzPickaxe.java new file mode 100644 index 00000000..cbc79d3a --- /dev/null +++ b/items/tools/quartz/ToolQuartzPickaxe.java @@ -0,0 +1,30 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.EnumToolMaterial; +import net.minecraft.item.ItemPickaxe; +import net.minecraftforge.common.MinecraftForge; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class ToolQuartzPickaxe extends ItemPickaxe implements IAEFeature +{ + + AEFeatureHandler feature; + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public ToolQuartzPickaxe(AEFeature Type) { + super( Configuration.instance.getItemID( ToolQuartzPickaxe.class, Type.name() ), EnumToolMaterial.IRON ); + MinecraftForge.setToolClass( this, "pickaxe", EnumToolMaterial.IRON.getHarvestLevel() ); + feature = new AEFeatureHandler( EnumSet.of( Type, AEFeature.QuartzPickaxe ), this, Type.name() ); + } + +} diff --git a/items/tools/quartz/ToolQuartzSpade.java b/items/tools/quartz/ToolQuartzSpade.java new file mode 100644 index 00000000..c157ea5f --- /dev/null +++ b/items/tools/quartz/ToolQuartzSpade.java @@ -0,0 +1,30 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.EnumToolMaterial; +import net.minecraft.item.ItemSpade; +import net.minecraftforge.common.MinecraftForge; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class ToolQuartzSpade extends ItemSpade implements IAEFeature +{ + + AEFeatureHandler feature; + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public ToolQuartzSpade(AEFeature Type) { + super( Configuration.instance.getItemID( ToolQuartzSpade.class, Type.name() ), EnumToolMaterial.IRON ); + MinecraftForge.setToolClass( this, "shovel", EnumToolMaterial.IRON.getHarvestLevel() ); + feature = new AEFeatureHandler( EnumSet.of( Type, AEFeature.QuartzSpade ), this, Type.name() ); + } + +} diff --git a/items/tools/quartz/ToolQuartzSword.java b/items/tools/quartz/ToolQuartzSword.java new file mode 100644 index 00000000..ad2bc29b --- /dev/null +++ b/items/tools/quartz/ToolQuartzSword.java @@ -0,0 +1,28 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.item.EnumToolMaterial; +import net.minecraft.item.ItemSword; +import appeng.core.Configuration; +import appeng.core.features.AEFeature; +import appeng.core.features.AEFeatureHandler; +import appeng.core.features.IAEFeature; + +public class ToolQuartzSword extends ItemSword implements IAEFeature +{ + + AEFeatureHandler feature; + + @Override + public AEFeatureHandler feature() + { + return feature; + } + + public ToolQuartzSword(AEFeature Type) { + super( Configuration.instance.getItemID( ToolQuartzSword.class, Type.name() ), EnumToolMaterial.IRON ); + feature = new AEFeatureHandler( EnumSet.of( Type, AEFeature.QuartzSword ), this, Type.name() ); + } + +} diff --git a/items/tools/quartz/ToolQuartzWrench.java b/items/tools/quartz/ToolQuartzWrench.java new file mode 100644 index 00000000..44b17ea2 --- /dev/null +++ b/items/tools/quartz/ToolQuartzWrench.java @@ -0,0 +1,68 @@ +package appeng.items.tools.quartz; + +import java.util.EnumSet; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IAEWrench; +import appeng.core.features.AEFeature; +import appeng.items.AEBaseItem; +import buildcraft.api.tools.IToolWrench; + +public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolWrench +{ + + public ToolQuartzWrench(AEFeature type) { + super( ToolQuartzWrench.class, type.name() ); + setfeature( EnumSet.of( type, AEFeature.QuartzWrench ) ); + setMaxStackSize( 1 ); + } + + @Override + public boolean onItemUseFirst(ItemStack is, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, + float hitY, float hitZ) + { + int id = world.getBlockId( x, y, z ); + if ( id > 0 ) + { + Block b = Block.blocksList[id]; + if ( b != null ) + { + if ( b.rotateBlock( world, x, y, z, ForgeDirection.getOrientation( side ) ) ) + { + player.swingItem(); + return !world.isRemote; + } + } + } + return false; + } + + @Override + public boolean shouldPassSneakingClickToBlock(World w, int x, int y, int z) + { + return true; + } + + @Override + public boolean canWrench(ItemStack is, EntityPlayer player, int x, int y, int z) + { + return true; + } + + @Override + public boolean canWrench(EntityPlayer player, int x, int y, int z) + { + return true; + } + + @Override + public void wrenchUsed(EntityPlayer player, int x, int y, int z) + { + player.swingItem(); + } + +} diff --git a/me/Grid.java b/me/Grid.java new file mode 100644 index 00000000..63e7e528 --- /dev/null +++ b/me/Grid.java @@ -0,0 +1,232 @@ +package appeng.me; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + +import appeng.api.AEApi; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IMachineSet; +import appeng.api.networking.events.MENetworkEvent; +import appeng.api.util.IReadOnlyCollection; +import appeng.core.WorldSettings; +import appeng.helpers.TickHandler; +import appeng.util.ReadOnlyCollection; + +public class Grid implements IGrid +{ + + GridStorage myStorage; + + NetworkEventBus bus = new NetworkEventBus(); + HashMap, Set> Machines = new HashMap, Set>(); + HashMap, GridCacheWrapper> caches = new HashMap, GridCacheWrapper>(); + + long LastFiveRemoveTime = 0; + long LastFiveAddNode = 0; + GridNode pivot; + + public Grid(GridNode center) { + this.pivot = center; + + HashMap, IGridCache> myCaches = AEApi.instance().registries().gridCache().createCacheInstance( this ); + for (Class c : myCaches.keySet()) + { + bus.readClass( c, myCaches.get( c ).getClass() ); + caches.put( c, new GridCacheWrapper( myCaches.get( c ) ) ); + } + + TickHandler.instance.addNetwork( this ); + center.setGrid( this ); + } + + public Set> getMachineClasses() + { + return Machines.keySet(); + } + + @Override + public IGridNode getPivot() + { + return pivot; + } + + public int size() + { + int out = 0; + for (Collection x : Machines.values()) + out += x.size(); + return out; + } + + public void remove(GridNode gridNode) + { + for (IGridCache c : caches.values()) + c.removeNode( this, gridNode, gridNode.getMachine() ); + + Collection nodes = Machines.get( gridNode.getMachineClass() ); + if ( nodes != null ) + nodes.remove( gridNode ); + + gridNode.setGridStorage( null ); + + if ( pivot == gridNode ) + { + Iterator n = getNodes().iterator(); + if ( n.hasNext() ) + pivot = (GridNode) n.next(); + else + { + pivot = null; + TickHandler.instance.removeNetwork( this ); + myStorage.remove(); + } + } + } + + public void add(GridNode gridNode) + { + Class mClass = gridNode.getMachineClass(); + Set nodes = Machines.get( mClass ); + if ( nodes == null ) + { + Machines.put( mClass, nodes = new MachineSet( mClass ) ); + bus.readClass( mClass, mClass ); + } + + // handle loading grid storages. + if ( gridNode.getGridStorage() != null ) + { + GridStorage gs = gridNode.getGridStorage(); + + if ( gs.getGrid() == null ) + { + myStorage = gs; + myStorage.setGrid( this ); + + for (IGridCache gc : caches.values()) + gc.onJoin( myStorage ); + } + else if ( gs.getGrid() != this ) + { + if ( myStorage == null ) + { + myStorage = WorldSettings.getInstance().getNewGridStorage(); + myStorage.setGrid( this ); + } + + GridStorage tmp = new GridStorage(); + if ( !gs.hasDivided( myStorage ) ) + { + gs.addDivided( myStorage ); + + for (IGridCache gc : ((Grid) gs.getGrid()).caches.values()) + gc.onSplit( tmp ); + + for (IGridCache gc : caches.values()) + gc.onJoin( tmp ); + } + } + } + else if ( myStorage == null ) + { + myStorage = WorldSettings.getInstance().getNewGridStorage(); + myStorage.setGrid( this ); + } + + // update grid node... + gridNode.setGridStorage( myStorage ); + + // track node. + nodes.add( gridNode ); + + for (IGridCache c : caches.values()) + c.addNode( this, gridNode, gridNode.getMachine() ); + + gridNode.gridProxy.gridChanged(); + // postEventTo( gridNode, networkChanged ); + } + + @Override + public boolean isReady() + { + return true; + } + + @Override + public IReadOnlyCollection getNodes() + { + return new NodeIteratable( Machines ); + } + + @Override + public IReadOnlyCollection> getMachinesClasses() + { + return new ReadOnlyCollection>( Machines.keySet() ); + } + + @Override + public IMachineSet getMachines(Class c) + { + MachineSet s = (MachineSet) Machines.get( c ); + if ( s == null ) + return new MachineSet( c ); + return s; + } + + @Override + public C getCache(Class iface) + { + return (C) caches.get( iface ).myCache; + } + + @Override + public MENetworkEvent postEventTo(IGridNode node, MENetworkEvent ev) + { + return bus.postEventTo( this, (GridNode) node, ev ); + } + + @Override + public MENetworkEvent postEvent(MENetworkEvent ev) + { + return bus.postEvent( this, ev ); + } + + public void requestSave() + { + myStorage.markDirty(); + WorldSettings.getInstance().save(); + } + + public void update() + { + for (IGridCache gc : caches.values()) + { + gc.onUpdateTick( this ); + } + } + + public Iterable getCacheWrappers() + { + return caches.values(); + } + + @Override + public boolean isEmpty() + { + return pivot == null; + } + + public void saveState() + { + for (IGridCache c : caches.values()) + { + c.populateGridStorage( myStorage ); + } + } + +} diff --git a/me/GridAccessException.java b/me/GridAccessException.java new file mode 100644 index 00000000..a9fa486a --- /dev/null +++ b/me/GridAccessException.java @@ -0,0 +1,8 @@ +package appeng.me; + +public class GridAccessException extends Exception +{ + + private static final long serialVersionUID = 3914554394866375300L; + +} diff --git a/me/GridCacheWrapper.java b/me/GridCacheWrapper.java new file mode 100644 index 00000000..eeff302c --- /dev/null +++ b/me/GridCacheWrapper.java @@ -0,0 +1,87 @@ +package appeng.me; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.me.cache.TickManagerCache; +import appeng.util.Platform; + +public class GridCacheWrapper implements IGridCache +{ + + final IGridCache myCache; + final public boolean isTickHandler; + + public long LastFiveTicksTime = 0; + public long LastFiveRemoveTime = 0; + public long LastFiveAddNode = 0; + + public GridCacheWrapper(IGridCache gc) { + myCache = gc; + isTickHandler = myCache instanceof TickManagerCache; + } + + @Override + public void onUpdateTick(IGrid grid) + { + long startTime = Platform.nanoTime(); + + myCache.onUpdateTick( grid ); + + long estimatedTime = Platform.nanoTime() - startTime; + + if ( isTickHandler ) // remove the ticking of tickables from the + // equation. + estimatedTime -= ((TickManagerCache) myCache).getInnerTime(); + + LastFiveTicksTime = ((LastFiveTicksTime * 4) / 5) + estimatedTime; + } + + @Override + public void removeNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + long startTime = Platform.nanoTime(); + + myCache.removeNode( grid, gridNode, machine ); + + long estimatedTime = Platform.nanoTime() - startTime; + LastFiveRemoveTime = ((LastFiveRemoveTime * 4) / 5) + estimatedTime; + } + + @Override + public void addNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + long startTime = Platform.nanoTime(); + + myCache.addNode( grid, gridNode, machine ); + + long estimatedTime = Platform.nanoTime() - startTime; + LastFiveAddNode = ((LastFiveAddNode * 4) / 5) + estimatedTime; + } + + public String getName() + { + return myCache.getClass().getName(); + } + + @Override + public void onSplit(IGridStorage storageB) + { + myCache.onSplit( storageB ); + } + + @Override + public void onJoin(IGridStorage storageB) + { + myCache.onJoin( storageB ); + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + myCache.populateGridStorage( storage ); + } + +} diff --git a/me/GridConnection.java b/me/GridConnection.java new file mode 100644 index 00000000..2d864b77 --- /dev/null +++ b/me/GridConnection.java @@ -0,0 +1,209 @@ +package appeng.me; + +import java.util.Arrays; +import java.util.EnumSet; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.pathing.IPathingGrid; +import appeng.api.util.IReadOnlyCollection; +import appeng.me.pathfinding.IPathItem; +import appeng.util.ReadOnlyCollection; + +public class GridConnection implements IGridConnection, IPathItem +{ + + final static private MENetworkChannelsChanged event = new MENetworkChannelsChanged(); + + private GridNode sideA; + private ForgeDirection fromAtoB; + private GridNode sideB; + + byte visitorIterationNumber = Byte.MIN_VALUE; + + public int channelData = 0; + + public GridConnection(IGridNode aNode, IGridNode bNode, ForgeDirection fromAtoB) { + + GridNode a = (GridNode) aNode; + GridNode b = (GridNode) bNode; + + if ( a == null || b == null ) + throw new GridException( "Connection Forged Between null entnties." ); + + if ( a.hasConnection( b ) || b.hasConnection( a ) ) + throw new GridException( "Connection already exists." ); + + sideA = a; + this.fromAtoB = fromAtoB; + sideB = b; + + if ( b.myGrid == null ) + { + b.setGrid( a.getInternalGrid() ); + } + else + { + if ( a.myGrid == null ) + { + GridPropagator gp = new GridPropagator( b.getInternalGrid() ); + a.beginVisition( gp ); + } + else if ( b.myGrid == null ) + { + GridPropagator gp = new GridPropagator( a.getInternalGrid() ); + b.beginVisition( gp ); + } + else if ( a.myGrid.size() > b.myGrid.size() ) + { + GridPropagator gp = new GridPropagator( a.getInternalGrid() ); + b.beginVisition( gp ); + } + else + { + GridPropagator gp = new GridPropagator( b.getInternalGrid() ); + a.beginVisition( gp ); + } + } + + // a connection was destroyed RE-PATH!! + IPathingGrid p = sideA.getInternalGrid().getCache( IPathingGrid.class ); + p.repath(); + + sideA.addConnection( this ); + sideB.addConnection( this ); + } + + @Override + public void destroy() + { + // a connection was destroyed RE-PATH!! + IPathingGrid p = sideA.getInternalGrid().getCache( IPathingGrid.class ); + p.repath(); + + sideA.removeConnection( this ); + sideB.removeConnection( this ); + + sideA.validateGrid(); + sideB.validateGrid(); + } + + @Override + public IGridNode a() + { + return sideA; + } + + @Override + public ForgeDirection getDirection(IGridNode side) + { + if ( fromAtoB == ForgeDirection.UNKNOWN ) + return fromAtoB; + + if ( sideA == side ) + return fromAtoB; + else + return fromAtoB.getOpposite(); + } + + @Override + public IGridNode b() + { + return sideB; + } + + @Override + public IGridNode getOtherSide(IGridNode gridNode) + { + if ( gridNode == sideA ) + return sideB; + if ( gridNode == sideB ) + return sideA; + + throw new GridException( "Invalid Side of Connection" ); + } + + @Override + public boolean hasDirection() + { + return fromAtoB != ForgeDirection.UNKNOWN; + } + + @Override + public IReadOnlyCollection getPossibleOptions() + { + return new ReadOnlyCollection( Arrays.asList( new IPathItem[] { (IPathItem) a(), (IPathItem) b() } ) ); + } + + @Override + public void incrementChannelCount(int usedChannels) + { + channelData += usedChannels; + } + + @Override + public boolean canSupportMoreChannels() + { + return getLastUsedChannels() < 32; // max, PERIOD. + } + + @Override + public int getUsedChannels() + { + return (channelData >> 8) & 0xff; + } + + public int getLastUsedChannels() + { + return channelData & 0xff; + } + + @Override + public IPathItem getControllerRoute() + { + if ( sideA.getFlags().contains( GridFlags.CANNOT_CARRY ) ) + return null; + return sideA; + } + + @Override + public void setControllerRoute(IPathItem fast, boolean zeroOut) + { + if ( zeroOut ) + channelData &= ~0xff; + + if ( sideB == fast ) + { + GridNode tmp = sideA; + sideA = sideB; + sideB = tmp; + fromAtoB = fromAtoB.getOpposite(); + } + } + + @Override + public void finalizeChannels() + { + if ( getUsedChannels() != getLastUsedChannels() ) + { + channelData = (channelData & 0xff); + channelData |= channelData << 8; + + if ( sideA.getInternalGrid() != null ) + sideA.getInternalGrid().postEventTo( sideA, event ); + + if ( sideB.getInternalGrid() != null ) + sideB.getInternalGrid().postEventTo( sideB, event ); + } + } + + @Override + public EnumSet getFlags() + { + return EnumSet.noneOf( GridFlags.class ); + } + +} diff --git a/me/GridException.java b/me/GridException.java new file mode 100644 index 00000000..ce0ee338 --- /dev/null +++ b/me/GridException.java @@ -0,0 +1,12 @@ +package appeng.me; + +public class GridException extends RuntimeException +{ + + private static final long serialVersionUID = -8110077032108243076L; + + public GridException(String s) { + + super( s ); + } +} diff --git a/me/GridNode.java b/me/GridNode.java new file mode 100644 index 00000000..f435d8ca --- /dev/null +++ b/me/GridNode.java @@ -0,0 +1,488 @@ +package appeng.me; + +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.GridNotification; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridConnecitonVisitor; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridVisitor; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.pathing.IPathingGrid; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.IReadOnlyCollection; +import appeng.core.WorldSettings; +import appeng.me.pathfinding.IPathItem; +import appeng.util.ReadOnlyCollection; + +public class GridNode implements IGridNode, IPathItem +{ + + final static private MENetworkChannelsChanged event = new MENetworkChannelsChanged(); + + final List Connections = new LinkedList(); + GridStorage myStorage = null; + + IGridBlock gridProxy; + Grid myGrid; + + public static byte currentVisitorIterationNumber = Byte.MIN_VALUE; + public static byte currentChannelsIterationNumber = Byte.MIN_VALUE; + + byte visitorIterationNumber = Byte.MIN_VALUE; + + // connection criteria + AEColor myColor = AEColor.Transparent; + EnumSet validDirections = EnumSet.noneOf( ForgeDirection.class ); + + // old power draw, used to diff + public double previousDraw = 0.0; + + private int maxChannels = 8; + private int channelData = 0; + + public int usedChannels() + { + return channelData >> 8; + } + + public AEColor getColor() + { + return myColor; + } + + public GridNode(IGridBlock what) { + gridProxy = what; + } + + @Override + public void loadFromNBT(String name, NBTTagCompound nodeData) + { + if ( myGrid == null ) + setGridStorage( WorldSettings.getInstance().getGridStorage( nodeData.getLong( name ) ) ); + else + throw new RuntimeException( "Loading data after part of a grid, this is invalid." ); + } + + @Override + public void saveToNBT(String name, NBTTagCompound nodeData) + { + if ( myStorage != null ) + nodeData.setLong( name, myStorage.getID() ); + else + nodeData.removeTag( name ); + } + + @Override + public IGridBlock getGridBlock() + { + return gridProxy; + } + + @Override + public EnumSet getConnectedSides() + { + EnumSet set = EnumSet.noneOf( ForgeDirection.class ); + for (IGridConnection gc : Connections) + set.add( gc.getDirection( this ) ); + return set; + } + + public Class getMachineClass() + { + return getMachine().getClass(); + } + + @Override + public IGridHost getMachine() + { + return gridProxy.getMachine(); + } + + @Override + public void updateState() + { + EnumSet set = gridProxy.getFlags(); + maxChannels = set.contains( GridFlags.CANNOT_CARRY ) ? 0 : (set.contains( GridFlags.TIER_2_CAPACITY ) ? 32 : 8); + myColor = gridProxy.getGridColor(); + validDirections = gridProxy.getConnectableSides(); + FindConnections(); + getInternalGrid(); + } + + @Override + public void beginVisition(IGridVisitor g) + { + currentVisitorIterationNumber++; + + LinkedList nextRun = new LinkedList(); + nextRun.add( this ); + + visitorIterationNumber = currentVisitorIterationNumber; + + if ( g instanceof IGridConnecitonVisitor ) + { + LinkedList nextConn = new LinkedList(); + IGridConnecitonVisitor gcv = (IGridConnecitonVisitor) g; + + while (!nextRun.isEmpty()) + { + while (!nextConn.isEmpty()) + gcv.visitConnection( nextConn.poll() ); + + LinkedList thisRun = nextRun; + nextRun = new LinkedList(); + + for (GridNode n : thisRun) + n.visitorConnection( g, nextRun, nextConn ); + } + } + else + { + while (!nextRun.isEmpty()) + { + LinkedList thisRun = nextRun; + nextRun = new LinkedList(); + + for (GridNode n : thisRun) + n.visitorNode( g, nextRun ); + } + } + } + + private void visitorConnection(IGridVisitor g, LinkedList nextRun, LinkedList nextConnections) + { + if ( g.visitNode( this ) ) + { + for (IGridConnection gc : getConnections()) + { + GridNode gn = (GridNode) gc.getOtherSide( this ); + GridConnection gcc = (GridConnection) gc; + + if ( gcc.visitorIterationNumber != currentVisitorIterationNumber ) + { + gcc.visitorIterationNumber = currentChannelsIterationNumber; + nextConnections.add( gc ); + } + + if ( currentVisitorIterationNumber == gn.visitorIterationNumber ) + continue; + + gn.visitorIterationNumber = currentVisitorIterationNumber; + + nextRun.add( gn ); + } + } + } + + private void visitorNode(IGridVisitor g, LinkedList nextRun) + { + if ( g.visitNode( this ) ) + { + for (IGridConnection gc : getConnections()) + { + GridNode gn = (GridNode) gc.getOtherSide( this ); + + if ( currentVisitorIterationNumber == gn.visitorIterationNumber ) + continue; + + gn.visitorIterationNumber = currentVisitorIterationNumber; + + nextRun.add( gn ); + } + } + } + + public void FindConnections() + { + if ( !gridProxy.isWorldAccessable() ) + return; + + DimensionalCoord dc = gridProxy.getLocation(); + for (ForgeDirection f : ForgeDirection.VALID_DIRECTIONS) + { + IGridHost te = findGridHost( dc.getWorld(), dc.x + f.offsetX, dc.y + f.offsetY, dc.z + f.offsetZ ); + if ( te != null ) + { + GridNode node = (GridNode) te.getGridNode( f.getOpposite() ); + if ( node == null ) + continue; + + boolean isValidConnection = this.canConnect( node, f ) && node.canConnect( this, f.getOpposite() ); + + IGridConnection con = null; // find the connection for this + // direction.. + for (IGridConnection c : getConnections()) + { + if ( c.getDirection( this ) == f ) + { + con = c; + break; + } + } + + if ( con != null ) + { + IGridNode os = (IGridNode) con.getOtherSide( this ); + if ( os == node ) + { + // if this connection is no longer valid, destroy it. + if ( !isValidConnection ) + con.destroy(); + } + else + { + throw new GridException( "invalid state found, encountered connection to phantom block." ); + } + } + else if ( isValidConnection ) + { + // construct a new connection between these two nodes. + new GridConnection( node, this, f.getOpposite() ); + } + + } + } + } + + private IGridHost findGridHost(World world, int x, int y, int z) + { + if ( world.blockExists( x, y, z ) ) + { + TileEntity te = world.getBlockTileEntity( x, y, z ); + if ( te instanceof IGridHost ) + return (IGridHost) te; + } + return null; + } + + public void addConnection(IGridConnection gridConnection) + { + Connections.add( gridConnection ); + if ( gridConnection.hasDirection() ) + gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); + } + + public void removeConnection(IGridConnection gridConnection) + { + Connections.remove( gridConnection ); + if ( gridConnection.hasDirection() ) + gridProxy.onGridNotification( GridNotification.ConnectionsChanged ); + } + + @Override + public IReadOnlyCollection getConnections() + { + return new ReadOnlyCollection( Connections ); + } + + public boolean hasConnection(IGridNode otherside) + { + for (IGridConnection gc : Connections) + { + if ( gc.a() == otherside || gc.b() == otherside ) + return true; + } + return false; + } + + public boolean canConnect(GridNode from, ForgeDirection dir) + { + if ( !validDirections.contains( dir ) ) + return false; + + if ( !from.getColor().matches( getColor() ) ) + return false; + + return true; + } + + @Override + public IGrid getGrid() + { + return myGrid; + } + + public Grid getInternalGrid() + { + if ( myGrid == null ) + myGrid = new Grid( this ); + + return myGrid; + } + + public void setGrid(Grid grid) + { + if ( myGrid == grid ) + return; + + if ( myGrid != null ) + { + myGrid.remove( this ); + + if ( myGrid.isEmpty() ) + { + myGrid.saveState(); + + for (IGridCache c : grid.caches.values()) + c.onJoin( myGrid.myStorage ); + } + } + + myGrid = grid; + myGrid.add( this ); + } + + public void validateGrid() + { + GridSplitDetector gsd = new GridSplitDetector( getInternalGrid().getPivot() ); + beginVisition( gsd ); + if ( !gsd.pivotFound ) + { + GridPropagator gp = new GridPropagator( new Grid( this ) ); + beginVisition( gp ); + } + } + + @Override + public void destroy() + { + while (!Connections.isEmpty()) + { + // not part of this network for real anymore. + if ( Connections.size() == 1 ) + setGridStorage( null ); + + IGridConnection c = Connections.listIterator().next(); + GridNode otherSide = (GridNode) c.getOtherSide( this ); + otherSide.getInternalGrid().pivot = otherSide; + c.destroy(); + } + + if ( myGrid != null ) + myGrid.remove( this ); + } + + @Override + public World getWorld() + { + return gridProxy.getLocation().getWorld(); + } + + @Override + public boolean meetsChannelRequirements() + { + return (!getGridBlock().getFlags().contains( GridFlags.REQURE_CHANNEL ) || getUsedChannels() > 0); + } + + @Override + public boolean isActive() + { + IGrid g = getGrid(); + if ( g != null ) + { + IPathingGrid pg = g.getCache( IPathingGrid.class ); + IEnergyGrid eg = g.getCache( IEnergyGrid.class ); + return meetsChannelRequirements() && eg.isNetworkPowered() && !pg.isNetworkBooting(); + } + return false; + } + + @Override + public boolean canSupportMoreChannels() + { + return getUsedChannels() < maxChannels; + } + + @Override + public IReadOnlyCollection getPossibleOptions() + { + return (ReadOnlyCollection) getConnections(); + } + + public int getLastUsedChannels() + { + return (channelData >> 8) & 0xff; + } + + public int getUsedChannels() + { + return channelData & 0xff; + } + + @Override + public void incrementChannelCount(int usedChannels) + { + channelData += usedChannels; + } + + public void setGridStorage(GridStorage s) + { + myStorage = s; + channelData = 0; + } + + public GridStorage getGridStorage() + { + return myStorage; + } + + @Override + public EnumSet getFlags() + { + return getGridBlock().getFlags(); + } + + @Override + public void finalizeChannels() + { + if ( getFlags().contains( GridFlags.CANNOT_CARRY ) ) + return; + + if ( getLastUsedChannels() != getUsedChannels() ) + { + channelData = (channelData & 0xff); + channelData |= channelData << 8; + + if ( getInternalGrid() != null ) + getInternalGrid().postEventTo( this, event ); + } + } + + @Override + public IPathItem getControllerRoute() + { + if ( Connections.isEmpty() || getFlags().contains( GridFlags.CANNOT_CARRY ) ) + return null; + + return (IPathItem) Connections.get( 0 ); + } + + @Override + public void setControllerRoute(IPathItem fast, boolean zeroOut) + { + if ( zeroOut ) + channelData &= ~0xff; + + int idx = Connections.indexOf( fast ); + if ( idx > 0 ) + { + Connections.remove( fast ); + Connections.add( 0, (IGridConnection) fast ); + } + } + +} diff --git a/me/GridPropagator.java b/me/GridPropagator.java new file mode 100644 index 00000000..366a721e --- /dev/null +++ b/me/GridPropagator.java @@ -0,0 +1,27 @@ +package appeng.me; + +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridVisitor; + +public class GridPropagator implements IGridVisitor +{ + + final private Grid g; + + public GridPropagator(Grid g) { + this.g = g; + } + + @Override + public boolean visitNode(IGridNode n) + { + GridNode gn = (GridNode) n; + if ( gn.myGrid != g || g.pivot == n ) + { + gn.setGrid( g ); + return true; + } + return false; + } + +} diff --git a/me/GridSplitDetector.java b/me/GridSplitDetector.java new file mode 100644 index 00000000..f478f93e --- /dev/null +++ b/me/GridSplitDetector.java @@ -0,0 +1,24 @@ +package appeng.me; + +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridVisitor; + +class GridSplitDetector implements IGridVisitor +{ + + final IGridNode pivot; + boolean pivotFound; + + public GridSplitDetector(IGridNode pivot) { + this.pivot = pivot; + } + + @Override + public boolean visitNode(IGridNode n) + { + if ( n == pivot ) + pivotFound = true; + + return !pivotFound; + } +}; diff --git a/me/GridStorage.java b/me/GridStorage.java new file mode 100644 index 00000000..9d9e7e64 --- /dev/null +++ b/me/GridStorage.java @@ -0,0 +1,141 @@ +package appeng.me; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; + +import org.bouncycastle.util.encoders.Base64; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridStorage; +import appeng.core.WorldSettings; + +public class GridStorage implements IGridStorage +{ + + IGrid myGrid = null; + + final long myID; + final NBTTagCompound data; + + public boolean isDirty = false; + private Set divlist = new HashSet(); + final GridStorageSearch mySearchEntry; // keep myself in the list until I'm lost... + + /** + * for use with world settings + * + * @param id + * @param gss + */ + public GridStorage(long id, GridStorageSearch gss) { + myID = id; + mySearchEntry = gss; + data = new NBTTagCompound(); + } + + /** + * for use with world settings + * + * @param input + * @param id + * @param gss + */ + public GridStorage(String input, long id, GridStorageSearch gss) { + myID = id; + mySearchEntry = gss; + NBTTagCompound myTag = null; + + try + { + byte[] dbata = Base64.decode( input ); + myTag = CompressedStreamTools.readCompressed( new ByteArrayInputStream( dbata ) ); + } + catch (Throwable t) + { + myTag = new NBTTagCompound(); + } + + data = myTag; + } + + /** + * fake storage. + */ + public GridStorage() { + myID = 0; + mySearchEntry = null; + data = new NBTTagCompound(); + } + + public String getValue() + { + isDirty = false; + + if ( myGrid != null ) + { + ((Grid) myGrid).saveState(); + } + + try + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + CompressedStreamTools.writeCompressed( data, out ); + return new String( Base64.encode( out.toByteArray() ), "UTF-8" ); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return ""; + } + + @Override + public NBTTagCompound dataObject() + { + return data; + } + + @Override + public long getID() + { + return myID; + } + + public void markDirty() + { + isDirty = true; + } + + public IGrid getGrid() + { + return myGrid; + } + + public void setGrid(Grid grid) + { + myGrid = grid; + } + + public void addDivided(GridStorage gs) + { + divlist.add( gs ); + } + + public boolean hasDivided(GridStorage myStorage) + { + return divlist.contains( myStorage ); + } + + public void remove() + { + WorldSettings.getInstance().destroyGridStorage( getID() ); + } + +} diff --git a/me/GridStorageSearch.java b/me/GridStorageSearch.java new file mode 100644 index 00000000..ca5afd5b --- /dev/null +++ b/me/GridStorageSearch.java @@ -0,0 +1,40 @@ +package appeng.me; + +import java.lang.ref.WeakReference; + +public class GridStorageSearch +{ + + final long id; + public WeakReference gridStorage; + + /** + * for use with the world settings + * + * @param id + */ + public GridStorageSearch(long id) { + this.id = id; + } + + @Override + public boolean equals(Object obj) + { + if ( obj == null ) + return false; + + GridStorageSearch b = (GridStorageSearch) obj; + + if ( id == b.id ) + return true; + + return false; + } + + @Override + public int hashCode() + { + return ((Long) id).hashCode(); + } + +} diff --git a/me/MachineSet.java b/me/MachineSet.java new file mode 100644 index 00000000..018c187b --- /dev/null +++ b/me/MachineSet.java @@ -0,0 +1,26 @@ +package appeng.me; + +import java.util.HashSet; + +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IMachineSet; + +public class MachineSet extends HashSet implements IMachineSet +{ + + private static final long serialVersionUID = 3224660708327386933L; + + private final Class machine; + + MachineSet(Class m) { + machine = m; + } + + @Override + public Class getMachineClass() + { + return machine; + } + +} diff --git a/me/NetworkEventBus.java b/me/NetworkEventBus.java new file mode 100644 index 00000000..9756d694 --- /dev/null +++ b/me/NetworkEventBus.java @@ -0,0 +1,153 @@ +package appeng.me; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; + +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkEvent; +import appeng.api.networking.events.MENetworkEventSubscribe; +import cpw.mods.fml.common.FMLLog; + +public class NetworkEventBus +{ + + class NetworkEventDone extends Throwable + { + + private static final long serialVersionUID = -3079021487019171205L; + + }; + + class MENetworkEventInfo + { + + public final Class objClass; + public final Method objMethod; + public final Class objEvent; + + public MENetworkEventInfo(Class Event, Class ObjClass, Method ObjMethod) { + this.objClass = ObjClass; + this.objMethod = ObjMethod; + this.objEvent = Event; + } + + public void invoke(Object obj, MENetworkEvent e) throws NetworkEventDone + { + try + { + objMethod.invoke( obj, e ); + } + catch (Throwable e1) + { + FMLLog.severe( "[AppEng] Network Event caused exception:" ); + FMLLog.severe( "Offending Class: " + obj.getClass().getName() ); + FMLLog.severe( "Offending Object: " + obj.toString() ); + e1.printStackTrace(); + throw new RuntimeException( e1 ); + } + + if ( e.isCanceled() ) + throw new NetworkEventDone(); + } + }; + + private static Set readClasses = new HashSet(); + private static Hashtable, Hashtable> events = new Hashtable(); + + public void readClass(Class listAs, Class c) + { + if ( readClasses.contains( c ) ) + return; + readClasses.add( c ); + + for (Method m : c.getMethods()) + { + MENetworkEventSubscribe s = m.getAnnotation( MENetworkEventSubscribe.class ); + if ( s != null ) + { + Class types[] = m.getParameterTypes(); + if ( types.length == 1 ) + { + if ( MENetworkEvent.class.isAssignableFrom( types[0] ) ) + { + + Hashtable classEvents = events.get( types[0] ); + if ( classEvents == null ) + events.put( types[0], classEvents = new Hashtable() ); + + classEvents.put( listAs, new MENetworkEventInfo( types[0], c, m ) ); + } + else + throw new RuntimeException( "Invalid ME Network Event Subscriber, " + m.getName() + "s Parameter must extend MENetworkEvent." ); + } + else + throw new RuntimeException( "Invalid ME Network Event Subscriber, " + m.getName() + " must have exactly 1 parameter." ); + } + } + + } + + public MENetworkEvent postEvent(Grid g, MENetworkEvent e) + { + Hashtable subscribers = events.get( e.getClass() ); + int x = 0; + + try + { + if ( subscribers != null ) + { + for (Class o : subscribers.keySet()) + { + MENetworkEventInfo target = subscribers.get( o ); + GridCacheWrapper cache = g.caches.get( o ); + if ( cache != null ) + { + x++; + target.invoke( cache.myCache, e ); + } + + for (IGridNode obj : g.getMachines( o )) + { + x++; + target.invoke( obj.getMachine(), e ); + } + } + } + } + catch (NetworkEventDone done) + { + // Early out. + } + + e.setVisitedObjects( x ); + return e; + } + + public MENetworkEvent postEventTo(Grid grid, GridNode node, MENetworkEvent e) + { + Hashtable subscribers = events.get( e.getClass() ); + int x = 0; + + try + { + if ( subscribers != null ) + { + MENetworkEventInfo target = subscribers.get( node.getMachineClass() ); + if ( target != null ) + { + x++; + target.invoke( node.getMachine(), e ); + } + } + } + catch (NetworkEventDone done) + { + // Early out. + } + + e.setVisitedObjects( x ); + return e; + } +} diff --git a/me/NodeIteratable.java b/me/NodeIteratable.java new file mode 100644 index 00000000..b2a25d68 --- /dev/null +++ b/me/NodeIteratable.java @@ -0,0 +1,57 @@ +package appeng.me; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + +import appeng.api.networking.IGridNode; +import appeng.api.util.IReadOnlyCollection; + +public class NodeIteratable implements IReadOnlyCollection +{ + + final private HashMap> Machines; + + public NodeIteratable(HashMap> Machines) { + this.Machines = Machines; + } + + @Override + public Iterator iterator() + { + return new NodeIterator( Machines ); + } + + @Override + public int size() + { + int size = 0; + + for (Set o : Machines.values()) + size += o.size(); + + return size; + } + + @Override + public boolean isEmpty() + { + for (Set o : Machines.values()) + if ( !o.isEmpty() ) + return false; + + return true; + } + + @Override + public boolean contains(Object node) + { + Class c = ((IGridNode) node).getMachine().getClass(); + + Set p = Machines.get( c ); + if ( p != null ) + return p.contains( node ); + + return false; + } +} diff --git a/me/NodeIterator.java b/me/NodeIterator.java new file mode 100644 index 00000000..c00c52f9 --- /dev/null +++ b/me/NodeIterator.java @@ -0,0 +1,53 @@ +package appeng.me; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; + +public class NodeIterator implements Iterator +{ + + boolean hasMore; + Iterator lvl1; + Iterator lvl2; + + boolean pull() + { + hasMore = lvl1.hasNext(); + if ( hasMore ) + { + lvl2 = ((Collection) lvl1.next()).iterator(); + return true; + } + return false; + } + + public NodeIterator(HashMap> machines) { + lvl1 = machines.values().iterator(); + pull(); + } + + @Override + public boolean hasNext() + { + if ( lvl2.hasNext() ) + return true; + if ( pull() ) + return hasNext(); + return hasMore; + } + + @Override + public IGridNode next() + { + return (IGridNode) lvl2.next(); + } + + @Override + public void remove() + { + lvl2.remove(); + } + +} diff --git a/me/cache/EnergyGridCache.java b/me/cache/EnergyGridCache.java new file mode 100644 index 00000000..1e918fb3 --- /dev/null +++ b/me/cache/EnergyGridCache.java @@ -0,0 +1,426 @@ +package appeng.me.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.energy.IEnergyGridProvider; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerIdleChange; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.events.MENetworkPowerStorage; +import appeng.me.GridNode; + +public class EnergyGridCache implements IEnergyGrid +{ + + /** + * estimated power available. + */ + int availableTicksSinceUpdate = 0; + double globalAvailablePower = 0; + + /** + * idle draw. + */ + double drainPerTick = 0; + Double[] totalDrainPastTicks = new Double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + Double[] totalInjectionPastTicks = new Double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + + /** + * power status + */ + boolean publicHasPower = false; + boolean hasPower = true; + long ticksSinceHasPowerChange = 900; + + /** + * excess power in the system. + */ + double prev_extra = 0; + double extra = 0; + + Set providers = new LinkedHashSet(); + Set requesters = new LinkedHashSet(); + + Set gproviders = new LinkedHashSet(); + + final IGrid myGrid; + + public EnergyGridCache(IGrid g) { + myGrid = g; + } + + @MENetworkEventSubscribe + public void EnergyNodeChanges(MENetworkPowerIdleChange ev) + { + // update power usage based on event. + GridNode node = (GridNode) ev.node; + IGridBlock gb = node.getGridBlock(); + + double newDraw = gb.getIdlePowerUsage(); + double diffDraw = newDraw - node.previousDraw; + node.previousDraw = newDraw; + + drainPerTick += diffDraw; + } + + @MENetworkEventSubscribe + public void EnergyNodeChanges(MENetworkPowerStorage ev) + { + if ( ev.storage.isAEPublicPowerStorage() ) + { + switch (ev.type) + { + case PROVIDE_POWER: + if ( ev.storage.getPowerFlow() != AccessRestriction.WRITE ) + providers.add( ev.storage ); + break; + case REQUEST_POWER: + if ( ev.storage.getPowerFlow() != AccessRestriction.READ ) + requesters.add( ev.storage ); + break; + } + } + else + { + (new RuntimeException( "Attempt to ask the IEnergyGrid to charge a non public energy store." )).printStackTrace(); + } + } + + @Override + public double getEnergyDemand(double maxRequired) + { + double required = 0; + Iterator it = requesters.iterator(); + while (required < maxRequired && it.hasNext()) + { + IAEPowerStorage node = it.next(); + if ( node.getPowerFlow() != AccessRestriction.READ ) + required += Math.max( 0.0, node.getAEMaxPower() - node.getAECurrentPower() ); + } + return required; + } + + @Override + public double injectPower(double i, Actionable mode) + { + i += extra; + + if ( mode == Actionable.SIMULATE ) + { + Iterator it = requesters.iterator(); + while (i > 0 && it.hasNext()) + { + IAEPowerStorage node = it.next(); + i = node.injectAEPower( i, Actionable.SIMULATE ); + } + } + else + { + while (i > 0 && !requesters.isEmpty()) + { + IAEPowerStorage node = requesters.iterator().next(); + + i = node.injectAEPower( i, Actionable.MODULATE ); + if ( i > 0 ) + requesters.remove( node ); + } + + extra = i; + totalInjectionPastTicks[0] += i; + } + + return i; + } + + @Override + public double extractAEPower(double amt, Actionable mode, PowerMultiplier pm) + { + return pm.divide( extractAEPower( pm.multiply( amt ), mode, new HashSet() ) ); + } + + @Override + public void addNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof IEnergyGridProvider ) + gproviders.add( (IEnergyGridProvider) machine ); + + // idle draw... + GridNode gnode = (GridNode) node; + IGridBlock gb = gnode.getGridBlock(); + gnode.previousDraw = gb.getIdlePowerUsage(); + drainPerTick += gnode.previousDraw; + + // power storage + if ( machine instanceof IAEPowerStorage ) + { + IAEPowerStorage ps = (IAEPowerStorage) machine; + if ( ps.isAEPublicPowerStorage() ) + { + double max = ps.getAEMaxPower(); + double current = ps.getAECurrentPower(); + + if ( current > 0 && ps.getPowerFlow() != AccessRestriction.WRITE ) + { + globalAvailablePower += ((IAEPowerStorage) machine).getAECurrentPower(); + providers.add( ps ); + } + + if ( current < max && ps.getPowerFlow() != AccessRestriction.READ ) + requesters.add( ps ); + } + } + + grid.postEventTo( node, new MENetworkPowerStatusChange() ); + } + + @Override + public void removeNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof IEnergyGridProvider ) + gproviders.remove( machine ); + + // idle draw. + GridNode gnode = (GridNode) node; + drainPerTick -= gnode.previousDraw; + + // power storage. + if ( machine instanceof IAEPowerStorage ) + { + IAEPowerStorage ps = (IAEPowerStorage) machine; + if ( ps.getPowerFlow() != AccessRestriction.WRITE ) + globalAvailablePower -= ps.getAECurrentPower(); + + providers.remove( machine ); + requesters.remove( machine ); + } + } + + // recalculate the whole thing? + public void reset(IGrid grid) + { + providers = new LinkedHashSet(); + requesters = new LinkedHashSet(); + + // re-calculate power info + for (Class c : grid.getMachinesClasses()) + { + if ( IAEPowerStorage.class.isAssignableFrom( c ) ) + { + for (Object obj : grid.getMachines( c )) + { + IAEPowerStorage ps = (IAEPowerStorage) obj; + if ( ps.isAEPublicPowerStorage() ) + { + double max = ps.getAEMaxPower(); + double current = ps.getAECurrentPower(); + + if ( current > 0 && ps.getPowerFlow() != AccessRestriction.WRITE ) + { + providers.add( ps ); + globalAvailablePower += ps.getAECurrentPower(); + } + + if ( current < max && ps.getPowerFlow() != AccessRestriction.READ ) + requesters.add( ps ); + + } + } + } + } + } + + @Override + public void onUpdateTick(IGrid grid) + { + // next tick is here... + for (int x = 0; x < totalDrainPastTicks.length - 1; x++) + totalDrainPastTicks[x + 1] = totalDrainPastTicks[x]; + totalDrainPastTicks[0] = 0.0; + + for (int x = 0; x < totalInjectionPastTicks.length - 1; x++) + totalInjectionPastTicks[x + 1] = totalInjectionPastTicks[x]; + totalInjectionPastTicks[0] = 0.0; + + // power information. + double drained = extractAEPower( getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG ); + boolean currentlyHasPower = drained >= drainPerTick - 0.1; + + // ticks since change.. + if ( currentlyHasPower == hasPower ) + ticksSinceHasPowerChange++; + else + ticksSinceHasPowerChange = 0; + + // update status.. + hasPower = currentlyHasPower; + + // update public status, this buffers power ups for 30 ticks. + if ( hasPower && ticksSinceHasPowerChange > 30 ) + publicPowerState( true, grid ); + else if ( !hasPower ) + publicPowerState( false, grid ); + + availableTicksSinceUpdate++; + if ( extra > 32 ) + injectPower( 0.0, Actionable.MODULATE ); + } + + private void publicPowerState(boolean newState, IGrid grid) + { + + if ( publicHasPower == newState ) + return; + + publicHasPower = newState; + grid.postEvent( new MENetworkPowerStatusChange() ); + } + + /** + * refresh current stored power. + */ + public void refreshPower() + { + availableTicksSinceUpdate = 0; + globalAvailablePower = 0; + for (IAEPowerStorage p : providers) + globalAvailablePower += p.getAECurrentPower(); + } + + @Override + public double getStoredPower() + { + if ( availableTicksSinceUpdate > 90 ) + refreshPower(); + + return globalAvailablePower; + } + + @Override + public double extractAEPower(double amt, Actionable mode, Set seen) + { + if ( seen.contains( this ) ) + return 0; + + seen.add( this ); + + double extractedPower = extra; + + if ( mode == Actionable.SIMULATE ) + { + Iterator it = providers.iterator(); + while (extractedPower < amt && it.hasNext()) + { + IAEPowerStorage node = it.next(); + + double req = amt - extractedPower; + double newPower = node.extractAEPower( req, Actionable.SIMULATE, PowerMultiplier.ONE ); + extractedPower += newPower; + } + } + else + { + extra = 0; + + while (extractedPower < amt && !providers.isEmpty()) + { + IAEPowerStorage node = providers.iterator().next(); + + double req = amt - extractedPower; + double newPower = node.extractAEPower( req, Actionable.MODULATE, PowerMultiplier.ONE ); + extractedPower += newPower; + + if ( newPower < req ) + providers.remove( node ); + } + + // add power used to the current tick. + totalDrainPastTicks[0] += extractedPower; + } + + // got more then we wanted? + if ( extractedPower > amt ) + { + extra = extractedPower - amt; + globalAvailablePower -= amt; + + return amt; + } + + if ( extractedPower < amt ) + { + for (IEnergyGridProvider egp : gproviders) + extractedPower += egp.extractAEPower( amt - extractedPower, mode, seen ); + } + + // go less or the correct amount? + globalAvailablePower -= extractedPower; + return extractedPower; + } + + @Override + public boolean isNetworkPowered() + { + return publicHasPower; + } + + @Override + public double getIdlePowerUsage() + { + return drainPerTick; + } + + @Override + public double getAvgPowerUsage() + { + double out = 0; + + for (double x : totalDrainPastTicks) + out += x; + + return out / totalDrainPastTicks.length; + } + + @Override + public double getAvgPowerInjection() + { + double out = 0; + + for (double x : totalInjectionPastTicks) + out += x; + + return out / totalInjectionPastTicks.length; + } + + @Override + public void onSplit(IGridStorage storageB) + { + extra /= 2; + storageB.dataObject().setDouble( "extraEnergy", extra ); + } + + @Override + public void onJoin(IGridStorage storageB) + { + extra += storageB.dataObject().getDouble( "extraEnergy" ); + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + storage.dataObject().setDouble( "extraEnergy", this.extra ); + } + +} diff --git a/me/cache/GridStorageCache.java b/me/cache/GridStorageCache.java new file mode 100644 index 00000000..c75a249a --- /dev/null +++ b/me/cache/GridStorageCache.java @@ -0,0 +1,208 @@ +package appeng.me.cache; + +import java.util.HashSet; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.ICellContainer; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +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.IItemList; +import appeng.me.storage.NetworkInventoryHandler; +import appeng.util.item.ItemList; + +public class GridStorageCache implements IStorageGrid +{ + + final HashSet cellContainers = new HashSet(); + final IGrid myGrid; + + private IItemList previousItemSet; + private NetworkInventoryHandler myItemNetwork; + private NetworkMonitor itemMonitor = new NetworkMonitor( this, StorageChannel.ITEMS ); + + private IItemList previousFluidSet; + private NetworkInventoryHandler myFluidNetwork; + private NetworkMonitor fluidMonitor = new NetworkMonitor( this, StorageChannel.FLUIDS ); + + public GridStorageCache(IGrid g) { + myGrid = g; + } + + @Override + public void onUpdateTick(IGrid grid) + { + itemMonitor.onTick(); + fluidMonitor.onTick(); + } + + @Override + public void removeNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof ICellContainer ) + { + ICellContainer cc = (ICellContainer) machine; + cellContainers.remove( cc ); + + for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.ITEMS )) + { + postChanges( StorageChannel.ITEMS, -1, h.getAvailableItems( new ItemList() ) ); + } + + for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.FLUIDS )) + { + postChanges( StorageChannel.ITEMS, -1, h.getAvailableItems( new ItemList() ) ); + } + } + + myGrid.postEvent( new MENetworkCellArrayUpdate() ); + } + + @Override + public void addNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof ICellContainer ) + { + ICellContainer cc = (ICellContainer) machine; + cellContainers.add( cc ); + + for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.ITEMS )) + { + postChanges( StorageChannel.ITEMS, 1, h.getAvailableItems( new ItemList() ) ); + } + + for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.FLUIDS )) + { + postChanges( StorageChannel.ITEMS, 1, h.getAvailableItems( new ItemList() ) ); + } + } + + myGrid.postEvent( new MENetworkCellArrayUpdate() ); + } + + private void buildNetworkStorage(StorageChannel chan) + { + switch (chan) + { + case FLUIDS: + myFluidNetwork = new NetworkInventoryHandler( StorageChannel.FLUIDS ); + for (ICellContainer cc : cellContainers) + { + for (IMEInventoryHandler h : cc.getCellArray( chan )) + myFluidNetwork.addNewStorage( h ); + } + break; + case ITEMS: + myItemNetwork = new NetworkInventoryHandler( StorageChannel.ITEMS ); + for (ICellContainer cc : cellContainers) + { + for (IMEInventoryHandler h : cc.getCellArray( chan )) + myItemNetwork.addNewStorage( h ); + } + break; + default: + } + } + + private void postChanges(StorageChannel chan, int up_or_down, IItemList availableItems) + { + switch (chan) + { + case FLUIDS: + for (IAEFluidStack fs : ((IItemList) availableItems)) + { + if ( up_or_down > 0 ) + fluidMonitor.postChange( fs ); + else + { + fs.setStackSize( -fs.getStackSize() ); + fluidMonitor.postChange( fs ); + } + } + break; + case ITEMS: + for (IAEItemStack fs : ((IItemList) availableItems)) + { + if ( up_or_down > 0 ) + itemMonitor.postChange( fs ); + else + { + fs.setStackSize( -fs.getStackSize() ); + itemMonitor.postChange( fs ); + } + } + break; + default: + } + } + + @MENetworkEventSubscribe + public void cellUpdate(MENetworkCellArrayUpdate ev) + { + myItemNetwork = null; + myFluidNetwork = null; + } + + public IMEInventoryHandler getItemInventoryHandler() + { + if ( myItemNetwork == null ) + buildNetworkStorage( StorageChannel.ITEMS ); + return myItemNetwork; + } + + public IMEInventoryHandler getFluidInventoryHandler() + { + if ( myFluidNetwork == null ) + buildNetworkStorage( StorageChannel.FLUIDS ); + return myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(StorageChannel chan, IAEStack input) + { + if ( chan == StorageChannel.ITEMS ) + itemMonitor.postChange( (IAEItemStack) input ); + else if ( chan == StorageChannel.FLUIDS ) + fluidMonitor.postChange( (IAEFluidStack) input ); + } + + @Override + public IMEMonitor getFluidInventory() + { + return fluidMonitor; + } + + @Override + public IMEMonitor getItemInventory() + { + return itemMonitor; + } + + @Override + public void onSplit(IGridStorage storageB) + { + + } + + @Override + public void onJoin(IGridStorage storageB) + { + + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + + } + +} diff --git a/me/cache/NetworkMonitor.java b/me/cache/NetworkMonitor.java new file mode 100644 index 00000000..028ee972 --- /dev/null +++ b/me/cache/NetworkMonitor.java @@ -0,0 +1,66 @@ +package appeng.me.cache; + +import java.util.LinkedList; + +import appeng.api.networking.events.MENetworkStorageEvent; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.MEMontorHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEStack; + +public class NetworkMonitor> extends MEMontorHandler +{ + + final private GridStorageCache myGridCache; + final private StorageChannel myChannel; + + boolean sendEvent = false; + + public NetworkMonitor(GridStorageCache cache, StorageChannel chan) { + super( null ); + myGridCache = cache; + myChannel = chan; + } + + final static public LinkedList depth = new LinkedList(); + + @Override + protected void postChange(T diff) + { + if ( depth.contains( this ) ) + return; + + depth.push( this ); + + sendEvent = true; + super.postChange( diff ); + + Object last = depth.pop(); + if ( last != this ) + throw new RuntimeException( "Invalid Access to Networked Storage API detected." ); + } + + public void onTick() + { + if ( sendEvent ) + { + sendEvent = false; + myGridCache.myGrid.postEvent( new MENetworkStorageEvent( getStorageList(), myChannel ) ); + } + } + + @Override + protected IMEInventoryHandler getHandler() + { + switch (myChannel) + { + case ITEMS: + return myGridCache.getItemInventoryHandler(); + case FLUIDS: + return myGridCache.getFluidInventoryHandler(); + default: + } + return null; + } + +} diff --git a/me/cache/P2PCache.java b/me/cache/P2PCache.java new file mode 100644 index 00000000..08114341 --- /dev/null +++ b/me/cache/P2PCache.java @@ -0,0 +1,103 @@ +package appeng.me.cache; + +import java.util.Collection; +import java.util.HashMap; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.parts.misc.PartP2PTunnel; + +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; + +public class P2PCache implements IGridCache +{ + + private HashMap inputs = new HashMap(); + private Multimap Tunnels = LinkedHashMultimap.create(); + + final IGrid myGrid; + + public P2PCache(IGrid g) { + myGrid = g; + } + + @Override + public void addNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof PartP2PTunnel ) + reset( grid ); + } + + @Override + public void removeNode(IGrid grid, IGridNode node, IGridHost machine) + { + if ( machine instanceof PartP2PTunnel ) + reset( grid ); + } + + public void reset(IGrid grid) + { + + Tunnels.clear(); + inputs.clear(); + + for (IGridNode n : grid.getMachines( PartP2PTunnel.class )) + { + PartP2PTunnel p = (PartP2PTunnel) n.getMachine(); + if ( p.freq > 0 ) + { + if ( p.output ) + Tunnels.put( p.freq, p ); + else if ( inputs.containsKey( p.freq ) ) + p.output = true; + else + inputs.put( p.freq, p ); + } + } + + for (PartP2PTunnel p : inputs.values()) + p.onChange(); + + for (PartP2PTunnel p : Tunnels.values()) + p.onChange(); + } + + public Collection getOutputs(long freq) + { + return Tunnels.get( freq ); + } + + public PartP2PTunnel getInput(long freq) + { + return inputs.get( freq ); + } + + @Override + public void onUpdateTick(IGrid grid) + { + + } + + @Override + public void onSplit(IGridStorage storageB) + { + + } + + @Override + public void onJoin(IGridStorage storageB) + { + + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + + } + +} diff --git a/me/cache/PathGridCache.java b/me/cache/PathGridCache.java new file mode 100644 index 00000000..4686a1aa --- /dev/null +++ b/me/cache/PathGridCache.java @@ -0,0 +1,279 @@ +package appeng.me.cache; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridMultiblock; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.api.networking.events.MENetworkBootingStatusChange; +import appeng.api.networking.events.MENetworkControllerChange; +import appeng.api.networking.pathing.ControllerState; +import appeng.api.networking.pathing.IPathingGrid; +import appeng.api.util.DimensionalCoord; +import appeng.me.GridConnection; +import appeng.me.GridNode; +import appeng.me.pathfinding.AdHocChannelUpdater; +import appeng.me.pathfinding.ControllerChannelUpdater; +import appeng.me.pathfinding.ControllerValidator; +import appeng.me.pathfinding.IPathItem; +import appeng.me.pathfinding.PathSegment; +import appeng.tile.networking.TileController; + +public class PathGridCache implements IPathingGrid +{ + + boolean recalculateControllerNextTick = true; + boolean updateNetwork = true; + boolean booting = false; + + LinkedList active = new LinkedList(); + + ControllerState controllerState = ControllerState.NO_CONTROLLER; + + int instance = Integer.MIN_VALUE; + + int ticksUntilReady = 20; + Set controllers = new HashSet(); + Set requireChannels = new HashSet(); + + final IGrid myGrid; + private HashSet semiOpen = new HashSet(); + private HashSet closedList = new HashSet(); + + public PathGridCache(IGrid g) { + myGrid = g; + } + + @Override + public void onUpdateTick(IGrid grid) + { + if ( recalculateControllerNextTick ) + { + recalcController(); + } + + if ( updateNetwork ) + { + if ( !booting ) + myGrid.postEvent( new MENetworkBootingStatusChange() ); + + booting = true; + updateNetwork = false; + instance++; + + if ( controllerState == ControllerState.NO_CONTROLLER ) + { + int requiredChannels = calculateRequiredChanels(); + int used = requiredChannels; + if ( requiredChannels > 8 ) + used = 0; + + int nodes = myGrid.getNodes().size(); + ticksUntilReady = 20 + (nodes / 10); + + myGrid.getPivot().beginVisition( new AdHocChannelUpdater( used ) ); + } + else if ( controllerState == ControllerState.CONTROLLER_CONFLICT ) + { + ticksUntilReady = 20; + myGrid.getPivot().beginVisition( new AdHocChannelUpdater( 0 ) ); + } + else + { + int nodes = myGrid.getNodes().size(); + ticksUntilReady = 20 + (nodes / 10); + closedList = new HashSet(); + semiOpen = new HashSet(); + + // myGrid.getPivot().beginVisition( new AdHocChannelUpdater( 0 ) ); + for (IGridNode node : grid.getMachines( TileController.class )) + { + closedList.add( (IPathItem) node ); + for (IGridConnection gcc : node.getConnections()) + { + GridConnection gc = (GridConnection) gcc; + if ( !(gc.getOtherSide( node ).getMachine() instanceof TileController) ) + { + List open = new LinkedList(); + closedList.add( gc ); + open.add( gc ); + gc.setControllerRoute( (GridNode) node, true ); + active.add( new PathSegment( open, semiOpen, closedList ) ); + } + } + } + } + } + + if ( !active.isEmpty() || ticksUntilReady > 0 ) + { + Iterator i = active.iterator(); + while (i.hasNext()) + { + PathSegment pat = i.next(); + if ( pat.step() ) + { + pat.isDead = true; + i.remove(); + } + } + + ticksUntilReady--; + + if ( active.isEmpty() && ticksUntilReady <= 0 ) + { + if ( controllerState == ControllerState.CONTROLLER_ONLINE ) + { + for (TileController tc : controllers) + { + tc.getGridNode( ForgeDirection.UNKNOWN ).beginVisition( new ControllerChannelUpdater() ); + break; + } + } + + booting = false; + myGrid.postEvent( new MENetworkBootingStatusChange() ); + } + } + } + + private int calculateRequiredChanels() + { + int depth = 0; + semiOpen.clear(); + + for (IGridNode nodes : requireChannels) + { + if ( !semiOpen.contains( nodes ) ) + { + depth++; + + IGridBlock gb = nodes.getGridBlock(); + if ( gb.getFlags().contains( GridFlags.MULTIBLOCK ) ) + { + IGridMultiblock gmb = (IGridMultiblock) gb; + Iterator i = gmb.getMultiblockNodes(); + while (i.hasNext()) + semiOpen.add( (IPathItem) i.next() ); + } + } + } + + return depth; + } + + @Override + public void repath() + { + // clean up... + active.clear(); + + updateNetwork = true; + } + + @Override + public void removeNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + if ( machine instanceof TileController ) + { + controllers.remove( machine ); + recalculateControllerNextTick = true; + } + + if ( gridNode.getGridBlock().getFlags().contains( GridFlags.REQURE_CHANNEL ) ) + requireChannels.remove( gridNode ); + + repath(); + } + + @Override + public void addNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + if ( machine instanceof TileController ) + { + controllers.add( (TileController) machine ); + recalculateControllerNextTick = true; + } + + if ( gridNode.getGridBlock().getFlags().contains( GridFlags.REQURE_CHANNEL ) ) + requireChannels.add( gridNode ); + + repath(); + } + + private void recalcController() + { + recalculateControllerNextTick = false; + ControllerState old = controllerState; + + if ( controllers.isEmpty() ) + { + controllerState = ControllerState.NO_CONTROLLER; + } + else + { + IGridNode startingNode = controllers.iterator().next().getGridNode( ForgeDirection.UNKNOWN ); + if ( startingNode == null ) + { + controllerState = ControllerState.CONTROLLER_CONFLICT; + return; + } + + DimensionalCoord dc = startingNode.getGridBlock().getLocation(); + ControllerValidator cv = new ControllerValidator( dc.x, dc.y, dc.z ); + + startingNode.beginVisition( cv ); + + if ( cv.isValid && cv.found == controllers.size() ) + controllerState = ControllerState.CONTROLLER_ONLINE; + else + controllerState = ControllerState.CONTROLLER_CONFLICT; + } + + if ( old != controllerState ) + { + myGrid.postEvent( new MENetworkControllerChange() ); + } + } + + @Override + public ControllerState getControllerState() + { + return controllerState; + } + + @Override + public boolean isNetworkBooting() + { + return !active.isEmpty(); + } + + @Override + public void onSplit(IGridStorage storageB) + { + + } + + @Override + public void onJoin(IGridStorage storageB) + { + + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + + } + +} diff --git a/me/cache/SpatialPylonCache.java b/me/cache/SpatialPylonCache.java new file mode 100644 index 00000000..08955d77 --- /dev/null +++ b/me/cache/SpatialPylonCache.java @@ -0,0 +1,219 @@ +package appeng.me.cache; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridCache; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.api.networking.events.MENetworkBootingStatusChange; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.spatial.ISpatialCache; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.IReadOnlyCollection; +import appeng.core.Configuration; +import appeng.me.cluster.implementations.SpatialPylonCluster; +import appeng.tile.spatial.TileSpatialIOPort; +import appeng.tile.spatial.TileSpatialPylon; + +public class SpatialPylonCache implements IGridCache, ISpatialCache +{ + + long powerRequired = 0; + + DimensionalCoord captureMin; + DimensionalCoord captureMax; + boolean isValid = false; + + List ioPorts = new LinkedList(); + HashMap clusters = new HashMap(); + + boolean needsUpdate = false; + + final IGrid myGrid; + + public SpatialPylonCache(IGrid g) { + myGrid = g; + } + + @Override + public boolean hasRegion() + { + return captureMin != null; + } + + @Override + public boolean isValidRegion() + { + return hasRegion() && isValid; + } + + @Override + public DimensionalCoord getMin() + { + return captureMin; + } + + @Override + public DimensionalCoord getMax() + { + return captureMax; + } + + public void reset(IGrid grid) + { + int reqX = 0; + int reqY = 0; + int reqZ = 0; + int requirePylongBlocks = 1; + + double effiency = 0.0; + double minPower = 0; + double maxPower = 0; + + clusters = new HashMap(); + ioPorts = new LinkedList(); + + for (IGridNode gm : grid.getMachines( TileSpatialIOPort.class )) + { + ioPorts.add( (TileSpatialIOPort) gm.getMachine() ); + } + + IReadOnlyCollection set = grid.getMachines( TileSpatialPylon.class ); + for (IGridNode gm : set) + { + if ( gm.isActive() ) + { + SpatialPylonCluster c = ((TileSpatialPylon) gm.getMachine()).getCluster(); + if ( c != null ) + clusters.put( c, c ); + } + } + + captureMax = null; + captureMin = null; + isValid = true; + + int pylonBlocks = 0; + for (SpatialPylonCluster cl : clusters.values()) + { + if ( captureMax == null ) + captureMax = cl.max.copy(); + if ( captureMin == null ) + captureMin = cl.min.copy(); + + pylonBlocks += cl.tileCount(); + + captureMin.x = Math.min( captureMin.x, cl.min.x ); + captureMin.y = Math.min( captureMin.y, cl.min.y ); + captureMin.z = Math.min( captureMin.z, cl.min.z ); + + captureMax.x = Math.max( captureMax.x, cl.max.x ); + captureMax.y = Math.max( captureMax.y, cl.max.y ); + captureMax.z = Math.max( captureMax.z, cl.max.z ); + } + + if ( hasRegion() ) + { + isValid = captureMax.x - captureMin.x > 1 && captureMax.y - captureMin.y > 1 && captureMax.z - captureMin.z > 1; + + for (SpatialPylonCluster cl : clusters.values()) + { + switch (cl.currentAxis) + { + case X: + + isValid = isValid && ((captureMax.y == cl.min.y || captureMin.y == cl.max.y) || (captureMax.z == cl.min.z || captureMin.z == cl.max.z)) + && ((captureMax.y == cl.max.y || captureMin.y == cl.min.y) || (captureMax.z == cl.max.z || captureMin.z == cl.min.z)); + + break; + case Y: + + isValid = isValid && ((captureMax.x == cl.min.x || captureMin.x == cl.max.x) || (captureMax.z == cl.min.z || captureMin.z == cl.max.z)) + && ((captureMax.x == cl.max.x || captureMin.x == cl.min.x) || (captureMax.z == cl.max.z || captureMin.z == cl.min.z)); + + break; + case Z: + + isValid = isValid && ((captureMax.y == cl.min.y || captureMin.y == cl.max.y) || (captureMax.x == cl.min.x || captureMin.x == cl.max.x)) + && ((captureMax.y == cl.max.y || captureMin.y == cl.min.y) || (captureMax.x == cl.max.x || captureMin.x == cl.min.x)); + + break; + case UNFORMED: + isValid = false; + break; + } + } + + reqX = captureMax.x - captureMin.x; + reqY = captureMax.y - captureMin.y; + reqZ = captureMax.z - captureMin.z; + requirePylongBlocks = ((reqX * reqZ + reqX * reqY + reqY * reqZ) * 3) / 5; + + effiency = (double) pylonBlocks / (double) requirePylongBlocks; + if ( effiency > 1.0 ) + effiency = 1.0; + if ( effiency < 0.0 ) + effiency = 0.0; + + minPower = (double) reqX * (double) reqY * reqZ * Configuration.instance.spatialPowerMultiplier; + maxPower = Math.pow( minPower, Configuration.instance.spatialPowerScaler ); + } + + double affective_effiency = Math.pow( effiency, 0.25 ); + powerRequired = (long) (affective_effiency * minPower + (1.0 - affective_effiency) * maxPower); + + for (SpatialPylonCluster cl : clusters.values()) + { + boolean myWasValid = cl.isValid; + cl.isValid = isValid; + if ( myWasValid != isValid ) + cl.updateStatus( false ); + } + } + + @MENetworkEventSubscribe + public void bootingRender(MENetworkBootingStatusChange c) + { + reset( myGrid ); + } + + @Override + public void onUpdateTick(IGrid grid) + { + } + + @Override + public void addNode(IGrid grid, IGridNode node, IGridHost machine) + { + + } + + @Override + public void removeNode(IGrid grid, IGridNode node, IGridHost machine) + { + + } + + @Override + public void onSplit(IGridStorage storageB) + { + + } + + @Override + public void onJoin(IGridStorage storageB) + { + + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + + } + +} diff --git a/me/cache/TickManagerCache.java b/me/cache/TickManagerCache.java new file mode 100644 index 00000000..d1cad0f3 --- /dev/null +++ b/me/cache/TickManagerCache.java @@ -0,0 +1,217 @@ +package appeng.me.cache; + +import java.util.HashMap; +import java.util.PriorityQueue; + +import net.minecraft.tileentity.TileEntity; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridStorage; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.core.AELog; +import appeng.me.cache.helpers.TickTracker; +import appeng.util.Platform; + +public class TickManagerCache implements ITickManager +{ + + private long currentTick = 0; + private long lastInnerTime = 0; + + final IGrid myGrid; + + public TickManagerCache(IGrid g) { + myGrid = g; + } + + HashMap alertable = new HashMap(); + + HashMap sleeping = new HashMap(); + HashMap awake = new HashMap(); + + PriorityQueue upcomingTicks = new PriorityQueue(); + + public long getCurrentTick() + { + return currentTick; + } + + public long getInnerTime() + { + return lastInnerTime; + } + + public long getAvgNanoTime(IGridNode node) + { + TickTracker tt = awake.get( node ); + + if ( tt == null ) + tt = sleeping.get( node ); + + if ( tt == null ) + return -1; + + return tt.getAvgNanos(); + } + + @Override + public void onUpdateTick(IGrid grid) + { + currentTick++; + while (!upcomingTicks.isEmpty()) + { + TickTracker tt = upcomingTicks.peek(); + int diff = (int) (currentTick - tt.lastTick); + if ( diff >= tt.current_rate ) + { + // remove tt.. + upcomingTicks.poll(); + + long startTime = Platform.nanoTime(); + TickRateModulation mod = tt.gt.tickingRequest( tt.node, diff ); + long estimatedTime = Platform.nanoTime() - startTime; + lastInnerTime += estimatedTime; + + tt.LastFiveTicksTime = ((tt.LastFiveTicksTime * 4) / 5) + estimatedTime; + + switch (mod) + { + case FASTER: + tt.setRate( tt.current_rate - 1 ); + break; + case IDLE: + tt.setRate( tt.request.maxTickRate ); + break; + case SAME: + break; + case SLEEP: + sleepDevice( tt.node ); + break; + case SLOWER: + tt.setRate( tt.current_rate + 1 ); + break; + case URGENT: + tt.setRate( 0 ); + break; + default: + break; + } + + if ( awake.containsKey( tt.node ) ) + addToQueue( tt ); + } + else + return; // done! + } + } + + private void addToQueue(TickTracker tt) + { + tt.lastTick = currentTick; + upcomingTicks.add( tt ); + } + + @Override + public boolean alertDevice(IGridNode node) + { + TickTracker tt = alertable.get( node ); + if ( tt == null ) + throw new RuntimeException( "Invalid Alertted device, this node is not marked as alertable, or part of this grid." ); + + tt.lastTick = -tt.request.maxTickRate; + addToQueue( tt ); + return true; + } + + @Override + public boolean sleepDevice(IGridNode node) + { + if ( awake.containsKey( node ) ) + { + TickTracker gt = awake.get( node ); + awake.remove( node ); + sleeping.put( node, gt ); + + return true; + } + + return false; + } + + @Override + public boolean wakeDevice(IGridNode node) + { + if ( sleeping.containsKey( node ) ) + { + TickTracker gt = sleeping.get( node ); + sleeping.remove( node ); + awake.put( node, gt ); + addToQueue( gt ); + + return true; + } + + return false; + } + + @Override + public void removeNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + if ( machine instanceof IGridTickable ) + { + alertable.remove( gridNode ); + sleeping.remove( gridNode ); + awake.remove( gridNode ); + } + } + + @Override + public void addNode(IGrid grid, IGridNode gridNode, IGridHost machine) + { + if ( machine instanceof IGridTickable ) + { + TickingRequest tr = ((IGridTickable) machine).getTickingRequest( gridNode ); + if ( tr != null ) + { + if ( machine instanceof TileEntity && ((TileEntity) machine).canUpdate() ) + AELog.warning( "Tile: " + machine.getClass().getName() + " - reports to use MC ticking, but also requests Network Based Ticking." ); + + TickTracker tt = new TickTracker( tr, gridNode, (IGridTickable) machine, currentTick, this ); + + if ( tr.canBeAlerted ) + alertable.put( gridNode, tt ); + + if ( tr.isSleeping ) + sleeping.put( gridNode, tt ); + else + { + awake.put( gridNode, tt ); + addToQueue( tt ); + } + + } + } + } + + @Override + public void onSplit(IGridStorage storageB) + { + + } + + @Override + public void onJoin(IGridStorage storageB) + { + + } + + @Override + public void populateGridStorage(IGridStorage storage) + { + + } +} diff --git a/me/cache/helpers/TickTracker.java b/me/cache/helpers/TickTracker.java new file mode 100644 index 00000000..9cc6869a --- /dev/null +++ b/me/cache/helpers/TickTracker.java @@ -0,0 +1,51 @@ +package appeng.me.cache.helpers; + +import appeng.api.networking.IGridNode; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickingRequest; +import appeng.me.cache.TickManagerCache; + +public class TickTracker implements Comparable +{ + + public final TickingRequest request; + public final IGridTickable gt; + public final IGridNode node; + public final TickManagerCache host; + + public long LastFiveTicksTime = 0; + + public long lastTick; + public int current_rate; + + public TickTracker(TickingRequest req, IGridNode node, IGridTickable gt, long currentTick, TickManagerCache tickManagerCache) { + request = req; + this.gt = gt; + this.node = node; + current_rate = (req.minTickRate + req.maxTickRate) / 2; + lastTick = currentTick; + host = tickManagerCache; + } + + public long getAvgNanos() + { + return (LastFiveTicksTime / 5); + } + + public void setRate(int rate) + { + current_rate = rate; + + if ( current_rate < request.minTickRate ) + current_rate = request.minTickRate; + + if ( current_rate > request.maxTickRate ) + current_rate = request.maxTickRate; + } + + @Override + public int compareTo(TickTracker t) + { + return (int) ((host.getCurrentTick() - lastTick) + current_rate); + } +}; diff --git a/me/cluster/IAECluster.java b/me/cluster/IAECluster.java new file mode 100644 index 00000000..c4308639 --- /dev/null +++ b/me/cluster/IAECluster.java @@ -0,0 +1,16 @@ +package appeng.me.cluster; + +import java.util.Iterator; + +import appeng.api.networking.IGridHost; + +public interface IAECluster +{ + + void updateStatus(boolean updateGrid); + + void destroy(); + + Iterator getTiles(); + +} diff --git a/me/cluster/IAEMultiBlock.java b/me/cluster/IAEMultiBlock.java new file mode 100644 index 00000000..28bd256f --- /dev/null +++ b/me/cluster/IAEMultiBlock.java @@ -0,0 +1,12 @@ +package appeng.me.cluster; + +public interface IAEMultiBlock +{ + + void disconnect(); + + IAECluster getCluster(); + + boolean isValid(); + +} diff --git a/me/cluster/MBCalculator.java b/me/cluster/MBCalculator.java new file mode 100644 index 00000000..6f5029de --- /dev/null +++ b/me/cluster/MBCalculator.java @@ -0,0 +1,194 @@ +package appeng.me.cluster; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.WorldCoord; +import appeng.util.Platform; + +public abstract class MBCalculator +{ + + private IAEMultiBlock target; + + public MBCalculator(IAEMultiBlock t) { + target = t; + } + + /** + * check if the tile entities are correct for the structure. + * + * @param te + * @return + */ + public abstract boolean isValidTile(TileEntity te); + + /** + * construct the correct cluster, usually very simple. + * + * @param w + * @param min + * @param max + * @return + */ + public abstract IAECluster createCluster(World w, WorldCoord min, WorldCoord max); + + /** + * configure the mutli-block tiles, most of the important stuff is in here. + * + * @param c + * @param w + * @param min + * @param max + */ + public abstract void updateTiles(IAECluster c, World w, WorldCoord min, WorldCoord max); + + /** + * disassembles the multi-block. + */ + public abstract void disconnect(); + + /** + * verify if the structure is the correct dimentions, or size + * + * @param min + * @param max + * @return + */ + public abstract boolean checkMultiblockScale(WorldCoord min, WorldCoord max); + + public boolean isValidTileAt(World w, int x, int y, int z) + { + return isValidTile( w.getBlockTileEntity( x, y, z ) ); + } + + public void calculateMultiblock(World worldObj, WorldCoord loc) + { + if ( Platform.isClient() ) + return; + + try + { + WorldCoord min = loc.copy(); + WorldCoord max = loc.copy(); + + World w = worldObj; + + // find size of MB structure... + while (isValidTileAt( w, min.x - 1, min.y, min.z )) + min.x--; + while (isValidTileAt( w, min.x, min.y - 1, min.z )) + min.y--; + while (isValidTileAt( w, min.x, min.y, min.z - 1 )) + min.z--; + while (isValidTileAt( w, max.x + 1, max.y, max.z )) + max.x++; + while (isValidTileAt( w, max.x, max.y + 1, max.z )) + max.y++; + while (isValidTileAt( w, max.x, max.y, max.z + 1 )) + max.z++; + + if ( checkMultiblockScale( min, max ) ) + { + if ( verifyUnownedRegion( w, min, max ) ) + { + IAECluster c = createCluster( w, min, max ); + + try + { + if ( !verifyInternalStructure( worldObj, min, max ) ) + { + disconnect(); + return; + } + } + catch (Exception err) + { + disconnect(); + return; + } + + boolean updateGrid = false; + IAECluster clust = target.getCluster(); + if ( clust == null ) + { + updateTiles( c, w, min, max ); + + updateGrid = true; + } + else + c = clust; + + c.updateStatus( updateGrid ); + return; + } + } + } + catch (Throwable err) + { + err.printStackTrace(); + } + + disconnect(); + } + + public abstract boolean verifyInternalStructure(World worldObj, WorldCoord min, WorldCoord max); + + public boolean verifyUnownedRegionInner(World w, int minx, int miny, int minz, int maxx, int maxy, int maxz, ForgeDirection side) + { + switch (side) + { + case WEST: + minx -= 1; + maxx = minx; + break; + case EAST: + maxx += 1; + minx = maxx; + break; + case DOWN: + miny -= 1; + maxy = miny; + break; + case NORTH: + maxz += 1; + minz = maxz; + break; + case SOUTH: + minz -= 1; + maxz = minz; + break; + case UP: + maxy += 1; + miny = maxy; + break; + case UNKNOWN: + return false; + } + + for (int x = minx; x <= maxx; x++) + { + for (int y = miny; y <= maxy; y++) + { + for (int z = minz; z <= maxz; z++) + { + TileEntity te = w.getBlockTileEntity( x, y, z ); + if ( isValidTile( te ) ) + return true; + } + } + } + + return false; + } + + public boolean verifyUnownedRegion(World w, WorldCoord min, WorldCoord max) + { + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + if ( verifyUnownedRegionInner( w, min.x, min.y, min.z, max.x, max.y, max.z, side ) ) + return false; + + return true; + } + +} diff --git a/me/cluster/implementations/IAssemblerCluster.java b/me/cluster/implementations/IAssemblerCluster.java new file mode 100644 index 00000000..1f9aadfd --- /dev/null +++ b/me/cluster/implementations/IAssemblerCluster.java @@ -0,0 +1,30 @@ +package appeng.me.cluster.implementations; + +import java.util.Iterator; + +import appeng.api.networking.IGridHost; +import appeng.me.cluster.IAECluster; + +public class IAssemblerCluster implements IAECluster +{ + + @Override + public void updateStatus(boolean updateGrid) + { + // TODO Auto-generated method stub + } + + @Override + public void destroy() + { + // TODO Auto-generated method stub + } + + @Override + public Iterator getTiles() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/me/cluster/implementations/QuantumCalculator.java b/me/cluster/implementations/QuantumCalculator.java new file mode 100644 index 00000000..cea24989 --- /dev/null +++ b/me/cluster/implementations/QuantumCalculator.java @@ -0,0 +1,130 @@ +package appeng.me.cluster.implementations; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import appeng.api.AEApi; +import appeng.api.util.WorldCoord; +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.me.cluster.MBCalculator; +import appeng.tile.qnb.TileQuantumBridge; +import appeng.util.Platform; + +public class QuantumCalculator extends MBCalculator +{ + + TileQuantumBridge tqb; + + public QuantumCalculator(IAEMultiBlock t) { + super( t ); + tqb = (TileQuantumBridge) t; + } + + @Override + public boolean isValidTile(TileEntity te) + { + return te instanceof TileQuantumBridge; + } + + @Override + public boolean checkMultiblockScale(WorldCoord min, WorldCoord max) + { + + if ( (max.x - min.x + 1) * (max.y - min.y + 1) * (max.z - min.z + 1) == 9 ) + { + int ones = ((max.x - min.x) == 0 ? 1 : 0) + ((max.y - min.y) == 0 ? 1 : 0) + ((max.z - min.z) == 0 ? 1 : 0); + + int threes = ((max.x - min.x) == 2 ? 1 : 0) + ((max.y - min.y) == 2 ? 1 : 0) + ((max.z - min.z) == 2 ? 1 : 0); + + return ones == 1 && threes == 2; + } + return false; + } + + @Override + public void updateTiles(IAECluster cl, World w, WorldCoord min, WorldCoord max) + { + byte num = 0; + byte ringNum = 0; + QuantumCluster c = (QuantumCluster) cl; + + for (int x = min.x; x <= max.x; x++) + { + for (int y = min.y; y <= max.y; y++) + { + for (int z = min.z; z <= max.z; z++) + { + TileQuantumBridge te = (TileQuantumBridge) w.getBlockTileEntity( x, y, z ); + + byte Fish = 0; + + num++; + if ( num == 5 ) + { + Fish = (byte) (num); + c.setCenter( te ); + } + else + { + if ( num == 1 || num == 3 || num == 7 || num == 9 ) + Fish = (byte) (tqb.corner | num); + else + Fish = (byte) (num); + c.Ring[ringNum++] = te; + } + + te.updateStatus( c, Fish ); + } + } + } + + } + + @Override + public IAECluster createCluster(World w, WorldCoord min, WorldCoord max) + { + return new QuantumCluster( min, max ); + } + + @Override + public void disconnect() + { + tqb.disconnect(); + } + + @Override + public boolean verifyInternalStructure(World w, WorldCoord min, WorldCoord max) + { + + byte num = 0; + + for (int x = min.x; x <= max.x; x++) + { + for (int y = min.y; y <= max.y; y++) + { + for (int z = min.z; z <= max.z; z++) + { + IAEMultiBlock te = (IAEMultiBlock) w.getBlockTileEntity( x, y, z ); + + if ( !te.isValid() ) + return false; + + num++; + if ( num == 5 ) + { + if ( Platform.blockAtLocationIs( w, x, y, z, AEApi.instance().blocks().blockQuantumLink ) ) + return false; + } + else + { + if ( Platform.blockAtLocationIs( w, x, y, z, AEApi.instance().blocks().blockQuantumRing ) ) + return false; + } + + } + } + } + return true; + } + +} diff --git a/me/cluster/implementations/QuantumCluster.java b/me/cluster/implementations/QuantumCluster.java new file mode 100644 index 00000000..8229cdbc --- /dev/null +++ b/me/cluster/implementations/QuantumCluster.java @@ -0,0 +1,224 @@ +package appeng.me.cluster.implementations; + +import java.util.Iterator; + +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.WorldEvent; +import appeng.api.AEApi; +import appeng.api.events.LocatableEventAnnounce; +import appeng.api.events.LocatableEventAnnounce.LocatableEvent; +import appeng.api.features.ILocatable; +import appeng.api.networking.IGridHost; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.WorldCoord; +import appeng.me.cluster.IAECluster; +import appeng.tile.qnb.TileQuantumBridge; +import appeng.util.iterators.ChainedIterator; + +public class QuantumCluster implements ILocatable, IAECluster +{ + + public WorldCoord min; + public WorldCoord max; + public boolean isDestroyed = false; + + boolean registered = false; + private long thisSide; + private long otherSide; + + public TileQuantumBridge Ring[]; + private TileQuantumBridge center; + + @Override + public Iterator getTiles() + { + return new ChainedIterator( Ring[0], Ring[1], Ring[2], Ring[3], Ring[4], Ring[5], Ring[6], Ring[7], center ); + } + + public void setCenter(TileQuantumBridge c) + { + registered = true; + MinecraftForge.EVENT_BUS.register( this ); + center = c; + } + + public QuantumCluster(WorldCoord _min, WorldCoord _max) { + min = _min; + max = _max; + Ring = new TileQuantumBridge[8]; + } + + public boolean canUseNode(long qe) + { + QuantumCluster qc = (QuantumCluster) AEApi.instance().registries().locateable().findLocateableBySerial( qe ); + if ( qc.center instanceof TileQuantumBridge ) + { + if ( !qc.isDestroyed ) + { + Chunk c = qc.center.worldObj.getChunkFromBlockCoords( qc.center.xCoord, qc.center.zCoord ); + if ( c.isChunkLoaded ) + return false; + } + } + return true; + } + + @ForgeSubscribe + public void onUnload(WorldEvent.Unload e) + { + if ( center.worldObj == e.world ) + { + destroy(); + } + } + + @Override + public void updateStatus(boolean updateGrid) + { + long oldOtherSide = otherSide; + long qe; + + qe = center.getQEDest(); + + if ( thisSide != qe && thisSide != -qe ) + { + if ( qe != 0 ) + { + if ( thisSide != 0 ) + MinecraftForge.EVENT_BUS.post( new LocatableEventAnnounce( this, LocatableEvent.Unregister ) ); + + if ( canUseNode( -qe ) ) + { + otherSide = qe; + thisSide = -qe; + } + else if ( canUseNode( qe ) ) + { + thisSide = qe; + otherSide = -qe; + } + + MinecraftForge.EVENT_BUS.post( new LocatableEventAnnounce( this, LocatableEvent.Register ) ); + } + else + { + MinecraftForge.EVENT_BUS.post( new LocatableEventAnnounce( this, LocatableEvent.Unregister ) ); + + otherSide = 0; + thisSide = 0; + } + } + + if ( updateGrid ) + { + updateGrid( this ); + Object myOtherSide = otherSide == 0 ? null : AEApi.instance().registries().locateable().findLocateableBySerial( otherSide ); + Object oldMyOtherSide = oldOtherSide == 0 ? null : AEApi.instance().registries().locateable().findLocateableBySerial( oldOtherSide ); + if ( myOtherSide instanceof QuantumCluster ) + updateGrid( (QuantumCluster) myOtherSide ); + if ( oldMyOtherSide instanceof QuantumCluster ) + updateGrid( (QuantumCluster) oldMyOtherSide ); + } + } + + public void updateRender() + { + for (int x = 0; x < Ring.length; x++) + { + + } + } + + private void updateGrid(QuantumCluster c) + { + + } + + @Override + public void destroy() + { + if ( isDestroyed ) + return; + isDestroyed = true; + + if ( registered ) + { + MinecraftForge.EVENT_BUS.unregister( this ); + registered = false; + } + + if ( getLocatableSerial() != 0 ) + { + updateGrid( this ); + Object myOtherSide = otherSide == 0 ? null : AEApi.instance().registries().locateable().findLocateableBySerial( otherSide ); + if ( myOtherSide instanceof QuantumCluster ) + updateGrid( (QuantumCluster) myOtherSide ); + + MinecraftForge.EVENT_BUS.post( new LocatableEventAnnounce( this, LocatableEvent.Unregister ) ); + } + + // updateStatus( true ); + + center.updateStatus( null, (byte) -1 ); + + for (TileQuantumBridge r : Ring) + { + r.updateStatus( null, (byte) -1 ); + } + + center = null; + Ring = new TileQuantumBridge[8]; + } + + public boolean isCorner(TileQuantumBridge tileQuantumBridge) + { + return Ring[0] == tileQuantumBridge || Ring[2] == tileQuantumBridge || Ring[4] == tileQuantumBridge || Ring[6] == tileQuantumBridge; + + } + + public DimensionalCoord[] getOtherSide() + { + Object myOtherSide = AEApi.instance().registries().locateable().findLocateableBySerial( otherSide ); + if ( myOtherSide != null ) + { + try + { + QuantumCluster qc = (QuantumCluster) myOtherSide; + DimensionalCoord[] out = new DimensionalCoord[4]; + out[0] = new DimensionalCoord( qc.Ring[1] ); + out[1] = new DimensionalCoord( qc.Ring[3] ); + out[2] = new DimensionalCoord( qc.Ring[4] ); + out[3] = new DimensionalCoord( qc.Ring[6] ); + return out; + } + catch (Throwable t) + { + } + } + return new DimensionalCoord[0]; + } + + @Override + public long getLocatableSerial() + { + return thisSide; + } + + public boolean hasPower() + { + return center.bridgePowered; + } + + public TileQuantumBridge getCenter() + { + return center; + } + + public boolean hasQES() + { + return getLocatableSerial() != 0; + } + +} diff --git a/me/cluster/implementations/SpatialPylonCalculator.java b/me/cluster/implementations/SpatialPylonCalculator.java new file mode 100644 index 00000000..24f7c731 --- /dev/null +++ b/me/cluster/implementations/SpatialPylonCalculator.java @@ -0,0 +1,88 @@ +package appeng.me.cluster.implementations; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.WorldCoord; +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.me.cluster.MBCalculator; +import appeng.tile.spatial.TileSpatialPylon; + +public class SpatialPylonCalculator extends MBCalculator +{ + + TileSpatialPylon tqb; + + public SpatialPylonCalculator(IAEMultiBlock t) { + super( t ); + tqb = (TileSpatialPylon) t; + } + + @Override + public boolean isValidTile(TileEntity te) + { + return te instanceof TileSpatialPylon; + } + + @Override + public boolean checkMultiblockScale(WorldCoord min, WorldCoord max) + { + return (min.x == max.x && min.y == max.y && min.z != max.z) || (min.x == max.x && min.y != max.y && min.z == max.z) || (min.x != max.x && min.y == max.y && min.z == max.z); + } + + @Override + public void updateTiles(IAECluster cl, World w, WorldCoord min, WorldCoord max) + { + SpatialPylonCluster c = (SpatialPylonCluster) cl; + + for (int x = min.x; x <= max.x; x++) + { + for (int y = min.y; y <= max.y; y++) + { + for (int z = min.z; z <= max.z; z++) + { + TileSpatialPylon te = (TileSpatialPylon) w.getBlockTileEntity( x, y, z ); + te.updateStatus( c ); + c.line.add( (te) ); + } + } + } + + } + + @Override + public IAECluster createCluster(World w, WorldCoord min, WorldCoord max) + { + return new SpatialPylonCluster( new DimensionalCoord( w, min.x, min.y, min.z ), new DimensionalCoord( w, max.x, max.y, max.z ) ); + } + + @Override + public void disconnect() + { + tqb.disconnect(); + } + + @Override + public boolean verifyInternalStructure(World w, WorldCoord min, WorldCoord max) + { + + for (int x = min.x; x <= max.x; x++) + { + for (int y = min.y; y <= max.y; y++) + { + for (int z = min.z; z <= max.z; z++) + { + IAEMultiBlock te = (IAEMultiBlock) w.getBlockTileEntity( x, y, z ); + + if ( !te.isValid() ) + return false; + + } + } + } + + return true; + } + +} diff --git a/me/cluster/implementations/SpatialPylonCluster.java b/me/cluster/implementations/SpatialPylonCluster.java new file mode 100644 index 00000000..471ce9da --- /dev/null +++ b/me/cluster/implementations/SpatialPylonCluster.java @@ -0,0 +1,80 @@ +package appeng.me.cluster.implementations; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import appeng.api.networking.IGridHost; +import appeng.api.util.DimensionalCoord; +import appeng.me.cluster.IAECluster; +import appeng.tile.spatial.TileSpatialPylon; + +public class SpatialPylonCluster implements IAECluster +{ + + public enum Axis + { + X, Y, Z, UNFORMED + }; + + public DimensionalCoord min; + public DimensionalCoord max; + public boolean isDestroyed = false; + + public Axis currentAxis = Axis.UNFORMED; + + List line = new ArrayList(); + public boolean isValid; + public boolean hasPower; + public boolean hasChannel; + + public SpatialPylonCluster(DimensionalCoord _min, DimensionalCoord _max) { + min = _min.copy(); + max = _max.copy(); + + if ( min.x != max.x ) + currentAxis = Axis.X; + else if ( min.y != max.y ) + currentAxis = Axis.Y; + else if ( min.z != max.z ) + currentAxis = Axis.Z; + else + currentAxis = Axis.UNFORMED; + } + + @Override + public void updateStatus(boolean updateGrid) + { + for (TileSpatialPylon r : line) + { + r.recalculateDisplay(); + } + } + + @Override + public void destroy() + { + + if ( isDestroyed ) + return; + isDestroyed = true; + + for (TileSpatialPylon r : line) + { + r.updateStatus( null ); + } + + } + + public int tileCount() + { + return line.size(); + } + + @Override + public Iterator getTiles() + { + return (Iterator) line.iterator(); + } + +} diff --git a/me/helpers/AENetworkProxy.java b/me/helpers/AENetworkProxy.java new file mode 100644 index 00000000..f3560f1c --- /dev/null +++ b/me/helpers/AENetworkProxy.java @@ -0,0 +1,299 @@ +package appeng.me.helpers; + +import java.util.EnumSet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.networking.GridFlags; +import appeng.api.networking.GridNotification; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.events.MENetworkPowerIdleChange; +import appeng.api.networking.pathing.IPathingGrid; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.IOrientable; +import appeng.helpers.TickHandler; +import appeng.me.GridAccessException; +import appeng.parts.networking.PartCable; +import appeng.tile.AEBaseTile; +import appeng.util.Platform; + +public class AENetworkProxy implements IGridBlock +{ + + final private IGridProxyable gp; + final private boolean worldNode; + + private boolean isReady = false; + private IGridNode node = null; + + private EnumSet validSides; + public AEColor myColor = AEColor.Transparent; + + private EnumSet flags = EnumSet.noneOf( GridFlags.class ); + private double idleDraw = 1.0; + + final private String nbtName; // name + NBTTagCompound data = null; // input + + public AENetworkProxy(IGridProxyable te, String nbtName, boolean inWorld) { + this.gp = te; + this.nbtName = nbtName; + worldNode = inWorld; + validSides = EnumSet.allOf( ForgeDirection.class ); + } + + public void writeToNBT(NBTTagCompound tag) + { + if ( node != null ) + node.saveToNBT( nbtName, tag ); + } + + public void readFromNBT(NBTTagCompound tag) + { + data = tag; + if ( node != null && data != null ) + { + node.loadFromNBT( nbtName, data ); + data = null; + } + } + + @Override + public DimensionalCoord getLocation() + { + return gp.getLocation(); + } + + @Override + public AEColor getGridColor() + { + return myColor; + } + + @Override + public void onGridNotification(GridNotification notification) + { + if ( gp instanceof PartCable ) + ((PartCable) gp).markForUpdate(); + } + + @Override + public void setNetworkStatus(IGrid grid, int channelsInUse) + { + + } + + @Override + public EnumSet getConnectableSides() + { + return validSides; + } + + @Override + public boolean isNetworkMachineActive() + { + if ( node == null ) + return false; + + return node.getGrid().isReady(); + } + + public void setValidSides(EnumSet validSides) + { + this.validSides = validSides; + if ( node != null ) + node.updateState(); + } + + public IGridNode getNode() + { + if ( node == null && Platform.isServer() && isReady ) + { + node = AEApi.instance().createGridNode( this ); + readFromNBT( data ); + node.updateState(); + } + + return node; + } + + public void validate() + { + if ( gp instanceof AEBaseTile ) + TickHandler.instance.addInit( (AEBaseTile) gp ); + } + + public void onChunkUnload() + { + isReady = false; + invalidate(); + } + + public void invalidate() + { + isReady = false; + if ( node != null ) + { + node.destroy(); + node = null; + } + } + + public void onReady() + { + isReady = true; + + // send orientation based directionality to the node. + if ( gp instanceof IOrientable ) + { + IOrientable ori = (IOrientable) gp; + if ( ori.canBeRotated() ) + ori.setOrientation( ori.getForward(), ori.getUp() ); + } + + getNode(); + } + + @Override + public IGridHost getMachine() + { + return gp; + } + + /** + * short cut! + * + * @return + * @throws GridAccessException + */ + public IGrid getGrid() throws GridAccessException + { + if ( node == null ) + throw new GridAccessException(); + IGrid grid = node.getGrid(); + if ( grid == null ) + throw new GridAccessException(); + return grid; + } + + public IEnergyGrid getEnergy() throws GridAccessException + { + IGrid grid = getGrid(); + if ( grid == null ) + throw new GridAccessException(); + IEnergyGrid eg = grid.getCache( IEnergyGrid.class ); + if ( eg == null ) + throw new GridAccessException(); + return eg; + } + + public IPathingGrid getPath() throws GridAccessException + { + IGrid grid = getGrid(); + if ( grid == null ) + throw new GridAccessException(); + IPathingGrid pg = grid.getCache( IPathingGrid.class ); + if ( pg == null ) + throw new GridAccessException(); + return pg; + } + + public ITickManager getTick() throws GridAccessException + { + IGrid grid = getGrid(); + if ( grid == null ) + throw new GridAccessException(); + ITickManager pg = grid.getCache( ITickManager.class ); + if ( pg == null ) + throw new GridAccessException(); + return pg; + } + + public IStorageGrid getStorage() throws GridAccessException + { + IGrid grid = getGrid(); + if ( grid == null ) + throw new GridAccessException(); + + IStorageGrid pg = grid.getCache( IStorageGrid.class ); + + if ( pg == null ) + throw new GridAccessException(); + + return pg; + } + + @Override + public boolean isWorldAccessable() + { + return worldNode; + } + + @Override + public EnumSet getFlags() + { + return flags; + } + + public void setFlags(GridFlags... requreChannel) + { + EnumSet flags = EnumSet.noneOf( GridFlags.class ); + + for (GridFlags gf : requreChannel) + flags.add( gf ); + + this.flags = flags; + } + + @Override + public double getIdlePowerUsage() + { + return idleDraw; + } + + public void setIdlePowerUsage(double idle) + { + idleDraw = idle; + + if ( node != null ) + { + try + { + IGrid g = getGrid(); + g.postEvent( new MENetworkPowerIdleChange( node ) ); + } + catch (GridAccessException e) + { + // not ready for this yet.. + } + } + } + + public boolean isReady() + { + return isReady; + } + + public boolean isActive() + { + if ( node == null ) + return false; + + return node.isActive(); + } + + @Override + public void gridChanged() + { + gp.gridChanged(); + } + +} diff --git a/me/helpers/AENetworkProxyMultiblock.java b/me/helpers/AENetworkProxyMultiblock.java new file mode 100644 index 00000000..fcc662b1 --- /dev/null +++ b/me/helpers/AENetworkProxyMultiblock.java @@ -0,0 +1,32 @@ +package appeng.me.helpers; + +import java.util.Iterator; + +import appeng.api.networking.IGridMultiblock; +import appeng.api.networking.IGridNode; +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.util.iterators.ChainedIterator; +import appeng.util.iterators.ProxyNodeIterator; + +public class AENetworkProxyMultiblock extends AENetworkProxy implements IGridMultiblock +{ + + IAECluster getCluster() + { + return ((IAEMultiBlock) getMachine()).getCluster(); + } + + public AENetworkProxyMultiblock(IGridProxyable te, String nbtName, boolean inWorld) { + super( te, nbtName, inWorld ); + } + + @Override + public Iterator getMultiblockNodes() + { + if ( getCluster() == null ) + return new ChainedIterator(); + + return new ProxyNodeIterator( getCluster().getTiles() ); + } +} diff --git a/me/helpers/IGridProxyable.java b/me/helpers/IGridProxyable.java new file mode 100644 index 00000000..631cda60 --- /dev/null +++ b/me/helpers/IGridProxyable.java @@ -0,0 +1,12 @@ +package appeng.me.helpers; + +import appeng.api.networking.IGridHost; +import appeng.api.util.DimensionalCoord; + +public interface IGridProxyable extends IGridHost +{ + + DimensionalCoord getLocation(); + + void gridChanged(); +} diff --git a/me/pathfinding/AdHocChannelUpdater.java b/me/pathfinding/AdHocChannelUpdater.java new file mode 100644 index 00000000..0d6936ff --- /dev/null +++ b/me/pathfinding/AdHocChannelUpdater.java @@ -0,0 +1,36 @@ +package appeng.me.pathfinding; + +import appeng.api.networking.IGridConnecitonVisitor; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridNode; +import appeng.me.GridConnection; +import appeng.me.GridNode; + +public class AdHocChannelUpdater implements IGridConnecitonVisitor +{ + + final private int usedChannels; + + public AdHocChannelUpdater(int used) { + usedChannels = used; + } + + @Override + public boolean visitNode(IGridNode n) + { + GridNode gn = (GridNode) n; + gn.setControllerRoute( null, true ); + gn.incrementChannelCount( usedChannels ); + gn.finalizeChannels(); + return true; + } + + @Override + public void visitConnection(IGridConnection gcc) + { + GridConnection gc = (GridConnection) gcc; + gc.setControllerRoute( null, true ); + gc.incrementChannelCount( usedChannels ); + gc.finalizeChannels(); + } +} diff --git a/me/pathfinding/ControllerChannelUpdater.java b/me/pathfinding/ControllerChannelUpdater.java new file mode 100644 index 00000000..c916d9f3 --- /dev/null +++ b/me/pathfinding/ControllerChannelUpdater.java @@ -0,0 +1,26 @@ +package appeng.me.pathfinding; + +import appeng.api.networking.IGridConnecitonVisitor; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridNode; +import appeng.me.GridConnection; +import appeng.me.GridNode; + +public class ControllerChannelUpdater implements IGridConnecitonVisitor +{ + + @Override + public boolean visitNode(IGridNode n) + { + GridNode gn = (GridNode) n; + gn.finalizeChannels(); + return true; + } + + @Override + public void visitConnection(IGridConnection gcc) + { + GridConnection gc = (GridConnection) gcc; + gc.finalizeChannels(); + } +} diff --git a/me/pathfinding/ControllerValidator.java b/me/pathfinding/ControllerValidator.java new file mode 100644 index 00000000..30551656 --- /dev/null +++ b/me/pathfinding/ControllerValidator.java @@ -0,0 +1,59 @@ +package appeng.me.pathfinding; + +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IGridVisitor; +import appeng.tile.networking.TileController; + +public class ControllerValidator implements IGridVisitor +{ + + int minX; + int minY; + int minZ; + + int maxX; + int maxY; + int maxZ; + + public boolean isValid = true; + public int found = 0; + + public ControllerValidator(int x, int y, int z) { + minX = x; + minY = y; + minZ = z; + maxX = x; + maxY = y; + maxZ = z; + } + + @Override + public boolean visitNode(IGridNode n) + { + IGridHost host = n.getMachine(); + if ( isValid && host instanceof TileController ) + { + TileController c = (TileController) host; + + minX = Math.min( c.xCoord, minX ); + maxX = Math.max( c.xCoord, maxX ); + minY = Math.min( c.yCoord, minY ); + maxY = Math.max( c.yCoord, maxY ); + minZ = Math.min( c.zCoord, minZ ); + maxZ = Math.max( c.zCoord, maxZ ); + + if ( maxX - minX < 7 && maxY - minY < 7 && maxZ - minZ < 7 ) + { + found++; + return true; + } + + isValid = false; + } + else + return false; + + return isValid; + } +} diff --git a/me/pathfinding/IPathItem.java b/me/pathfinding/IPathItem.java new file mode 100644 index 00000000..6b46941e --- /dev/null +++ b/me/pathfinding/IPathItem.java @@ -0,0 +1,44 @@ +package appeng.me.pathfinding; + +import java.util.EnumSet; + +import appeng.api.networking.GridFlags; +import appeng.api.util.IReadOnlyCollection; + +public interface IPathItem +{ + + IPathItem getControllerRoute(); + + void setControllerRoute(IPathItem fast, boolean zeroOut); + + /** + * used to determine if the finder can continue. + */ + boolean canSupportMoreChannels(); + + /** + * find possible choices for other pathing. + */ + IReadOnlyCollection getPossibleOptions(); + + /** + * add one to the channel count, this is mostly for cables. + */ + void incrementChannelCount(int usedChannels); + + /** + * get the grid flags for this IPathItem. + * + * @return the flag set. + */ + public EnumSet getFlags(); + + /** + * channels are done, wrap it up. + * + * @return + */ + void finalizeChannels(); + +} diff --git a/me/pathfinding/PathSegment.java b/me/pathfinding/PathSegment.java new file mode 100644 index 00000000..26b60adb --- /dev/null +++ b/me/pathfinding/PathSegment.java @@ -0,0 +1,132 @@ +package appeng.me.pathfinding; + +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGridMultiblock; +import appeng.api.networking.IGridNode; + +public class PathSegment +{ + + public boolean isDead; + + static class RouteComplete extends Exception + { + + private static final long serialVersionUID = 810456465120286110L; + + }; + + public PathSegment(List open, Set semiopen, Set closed) { + this.open = open; + this.semiopen = semiopen; + this.closed = closed; + isDead = false; + } + + List open; + Set semiopen; + Set closed; + + public boolean step() + { + List oldOpen = open; + open = new LinkedList(); + + for (IPathItem i : oldOpen) + { + for (IPathItem pi : i.getPossibleOptions()) + { + EnumSet flags = pi.getFlags(); + + if ( !closed.contains( pi ) ) + { + pi.setControllerRoute( i, true ); + + if ( flags.contains( GridFlags.REQURE_CHANNEL ) ) + { + // close the semi open. + if ( !semiopen.contains( pi ) ) + { + boolean worked = false; + + if ( flags.contains( GridFlags.DENSE_CHANNEL ) ) + worked = useDenseChannel( pi ); + else + worked = useChannel( pi ); + + if ( worked && flags.contains( GridFlags.MULTIBLOCK ) ) + { + Iterator oni = ((IGridMultiblock) ((IGridNode) pi).getGridBlock()).getMultiblockNodes(); + while (oni.hasNext()) + { + IGridNode otherNodes = oni.next(); + if ( otherNodes != pi ) + semiopen.add( (IPathItem) otherNodes ); + } + } + } + else + { + pi.incrementChannelCount( 1 ); // give a channel. + semiopen.remove( pi ); + } + } + + closed.add( pi ); + open.add( pi ); + } + } + } + + return open.isEmpty(); + } + + private boolean useChannel(IPathItem start) + { + IPathItem pi = start; + while (pi != null) + { + if ( !pi.canSupportMoreChannels() ) + return false; + + pi = pi.getControllerRoute(); + } + + pi = start; + while (pi != null) + { + pi.incrementChannelCount( 1 ); + pi = pi.getControllerRoute(); + } + + return true; + } + + private boolean useDenseChannel(IPathItem start) + { + IPathItem pi = start; + while (pi != null) + { + if ( !pi.canSupportMoreChannels() || pi.getFlags().contains( GridFlags.CANNOT_CARRY_DENSE ) ) + return false; + + pi = pi.getControllerRoute(); + } + + pi = start; + while (pi != null) + { + pi.incrementChannelCount( 1 ); + pi = pi.getControllerRoute(); + } + + return true; + } + +} diff --git a/me/storage/AEExternalHandler.java b/me/storage/AEExternalHandler.java new file mode 100644 index 00000000..6ed81d37 --- /dev/null +++ b/me/storage/AEExternalHandler.java @@ -0,0 +1,66 @@ +package appeng.me.storage; + +import net.minecraft.inventory.IInventory; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.tile.misc.TileCondenser; + +public class AEExternalHandler implements IExternalStorageHandler +{ + + @Override + public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel channel) + { + if ( channel == StorageChannel.ITEMS && te instanceof IStorageMonitorable ) + return true; + + if ( channel == StorageChannel.ITEMS && te instanceof IInventory ) + return true; + + return te instanceof TileCondenser; + } + + @Override + public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel channel) + { + if ( te instanceof TileCondenser ) + { + if ( channel == StorageChannel.ITEMS ) + return new VoidItemInventory( (TileCondenser) te ); + else + return new VoidFluidInventory( (TileCondenser) te ); + } + + if ( te instanceof IStorageMonitorable ) + { + IStorageMonitorable iface = (IStorageMonitorable) te; + + if ( channel == StorageChannel.ITEMS ) + { + IMEInventory ii = iface.getItemInventory(); + if ( ii != null ) + return ii; + } + + if ( channel == StorageChannel.FLUIDS ) + { + IMEInventory fi = iface.getFluidInventory(); + if ( fi != null ) + return fi; + } + } + + if ( channel == StorageChannel.ITEMS && te instanceof IInventory ) + { + return new MEMonitorIInventory( (IInventory) te, d ); + } + + return null; + } +} diff --git a/me/storage/CellInventory.java b/me/storage/CellInventory.java new file mode 100644 index 00000000..0ee324ea --- /dev/null +++ b/me/storage/CellInventory.java @@ -0,0 +1,485 @@ +package appeng.me.storage; + +import java.util.HashSet; +import java.util.Iterator; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagShort; +import net.minecraftforge.oredict.OreDictionary; +import appeng.api.config.Actionable; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.IStorageCell; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; +import appeng.util.item.ItemList; + +public class CellInventory implements IMEInventory +{ + + static final String ITEM_TYPE_TAG = "it"; + static final String ITEM_COUNT_TAG = "ic"; + static final String ITEM_SLOT = "#"; + static final String ITEM_SLOTCOUNT = "@"; + static final String ITEM_PRE_FORMATED_COUNT = "PF"; + static final String ITEM_PRE_FORMATED_SLOT = "PF#"; + static final String ITEM_PRE_FORMATED_NAME = "PN"; + static final String ITEM_PRE_FORMATED_FUZZY = "FP"; + + static protected String[] ITEM_SLOT_ARR; + static protected String[] ITEM_SLOTCOUNT_ARR; + + final protected NBTTagCompound tagCompound; + protected int MAX_ITEM_TYPES = 63; + protected short storedItems = 0; + protected int storedItemCount = 0; + protected ItemList cellItems; + + protected ItemStack i; + protected IStorageCell CellType; + + protected CellInventory(NBTTagCompound data) { + tagCompound = data; + } + + protected void loadCellItems() + { + if ( cellItems == null ) + cellItems = new ItemList(); + + cellItems.resetStatus(); // clears totals and stuff. + + int types = (int) storedItemTypes(); + + for (int x = 0; x < types; x++) + { + ItemStack t = ItemStack.loadItemStackFromNBT( tagCompound.getCompoundTag( ITEM_SLOT_ARR[x] ) ); + if ( t != null ) + { + t.stackSize = tagCompound.getInteger( ITEM_SLOTCOUNT_ARR[x] ); + + if ( t.stackSize > 0 ) + { + cellItems.add( AEItemStack.create( t ) ); + } + } + } + + // cellItems.clean(); + } + + void saveChanges() + { + // cellItems.clean(); + int itemCount = 0; + + // add new pretty stuff... + int x = 0; + Iterator i = cellItems.iterator(); + while (i.hasNext()) + { + IAEItemStack v = i.next(); + itemCount += v.getStackSize(); + + NBTBase c = tagCompound.getTag( ITEM_SLOT_ARR[x] ); + if ( c instanceof NBTTagCompound ) + v.writeToNBT( (NBTTagCompound) c ); + else + { + NBTTagCompound g = new NBTTagCompound(); + v.writeToNBT( g ); + tagCompound.setCompoundTag( ITEM_SLOT_ARR[x], g ); + } + + NBTBase tagSlotCount = tagCompound.getTag( ITEM_SLOTCOUNT_ARR[x] ); + if ( tagSlotCount instanceof NBTTagInt ) + ((NBTTagInt) tagSlotCount).data = (int) v.getStackSize(); + else + tagCompound.setInteger( ITEM_SLOTCOUNT_ARR[x], (int) v.getStackSize() ); + + x++; + } + + NBTBase tagType = tagCompound.getTag( ITEM_TYPE_TAG ); + NBTBase tagCount = tagCompound.getTag( ITEM_COUNT_TAG ); + short oldStoreditems = storedItems; + + if ( tagType instanceof NBTTagShort ) + ((NBTTagShort) tagType).data = storedItems = (short) cellItems.size(); + else + tagCompound.setShort( ITEM_TYPE_TAG, storedItems = (short) cellItems.size() ); + + if ( tagCount instanceof NBTTagInt ) + ((NBTTagInt) tagCount).data = storedItemCount = itemCount; + else + tagCompound.setInteger( ITEM_COUNT_TAG, storedItemCount = itemCount ); + + // clean any old crusty stuff... + for (; x < oldStoreditems && x < MAX_ITEM_TYPES; x++) + { + tagCompound.removeTag( ITEM_SLOT_ARR[x] ); + tagCompound.removeTag( ITEM_SLOTCOUNT_ARR[x] ); + } + } + + protected CellInventory(ItemStack o) throws AppEngException { + if ( ITEM_SLOT_ARR == null ) + { + ITEM_SLOT_ARR = new String[MAX_ITEM_TYPES]; + ITEM_SLOTCOUNT_ARR = new String[MAX_ITEM_TYPES]; + + for (int x = 0; x < MAX_ITEM_TYPES; x++) + { + ITEM_SLOT_ARR[x] = ITEM_SLOT + x; + ITEM_SLOTCOUNT_ARR[x] = ITEM_SLOTCOUNT + x; + } + } + + if ( o == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + CellType = null; + i = o; + + Item type = i.getItem(); + if ( type instanceof IStorageCell ) + { + CellType = (IStorageCell) i.getItem(); + MAX_ITEM_TYPES = CellType.getTotalTypes( i ); + } + + if ( CellType == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + if ( !CellType.isStorageCell( i ) ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + if ( MAX_ITEM_TYPES > 63 ) + MAX_ITEM_TYPES = 63; + if ( MAX_ITEM_TYPES < 1 ) + MAX_ITEM_TYPES = 1; + + tagCompound = Platform.openNbtData( o ); + storedItems = tagCompound.getShort( ITEM_TYPE_TAG ); + storedItemCount = tagCompound.getInteger( ITEM_COUNT_TAG ); + cellItems = null; + } + + ItemList getCellItems() + { + if ( cellItems == null ) + { + cellItems = new ItemList(); + loadCellItems(); + } + + return cellItems; + } + + public int BytesPerType() + { + return CellType.BytePerType( i ); + } + + public boolean canHoldNewItem() + { + long bytesFree = freeBytes(); + return (bytesFree > BytesPerType() || (bytesFree == BytesPerType() && unusedItemCount() > 0)) && remainingItemTypes() > 0; + } + + public static IMEInventoryHandler getCell(ItemStack o) + { + try + { + return new CellInventoryHandler( new CellInventory( o ) ); + } + catch (AppEngException e) + { + return null; + } + } + + private static boolean isStorageCell(ItemStack i) + { + if ( i == null ) + { + return false; + } + + try + { + Item type = i.getItem(); + if ( type instanceof IStorageCell ) + { + return !((IStorageCell) type).storableInStorageCell(); + } + } + catch (Throwable err) + { + return true; + } + + return false; + } + + public static boolean isCell(ItemStack i) + { + if ( i == null ) + { + return false; + } + + Item type = i.getItem(); + if ( type instanceof IStorageCell ) + { + return ((IStorageCell) type).isStorageCell( i ); + } + + return false; + } + + public long totalBytes() + { + return CellType.getBytes( i ); + } + + public long freeBytes() + { + return totalBytes() - usedBytes(); + } + + public long usedBytes() + { + long bytesForItemCount = (storedItemCount() + unusedItemCount()) / 8; + return storedItemTypes() * BytesPerType() + bytesForItemCount; + } + + public long getTotalItemTypes() + { + return MAX_ITEM_TYPES; + } + + public long storedItemTypes() + { + return storedItems; + } + + public long storedItemCount() + { + return storedItemCount; + } + + private void updateItemCount(long delta) + { + tagCompound.setInteger( ITEM_COUNT_TAG, storedItemCount = (int) (storedItemCount + delta) ); + } + + public long remainingItemTypes() + { + long basedOnStorage = freeBytes() / BytesPerType(); + long baseOnTotal = getTotalItemTypes() - storedItemTypes(); + return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage; + } + + public long remainingItemCount() + { + long remaining = freeBytes() * 8 + unusedItemCount(); + return remaining > 0 ? remaining : 0; + } + + // returns the number of items that can be added without using an additional + // byte! + public int unusedItemCount() + { + int div = (int) (storedItemCount() % 8); + + if ( div == 0 ) + { + return 0; + } + + return 8 - div; + } + + private static HashSet blackList = new HashSet(); + + public static void addBasicBlackList(int itemID, int Meta) + { + blackList.add( (Meta << Platform.DEF_OFFSET) | itemID ); + } + + public static boolean isBlackListed(IAEItemStack input) + { + if ( blackList.contains( (OreDictionary.WILDCARD_VALUE << Platform.DEF_OFFSET) | input.getItem().itemID ) ) + return true; + return blackList.contains( (input.getItemDamage() << Platform.DEF_OFFSET) | input.getItem().itemID ); + } + + private boolean isEmpty(IMEInventory meinv) + { + return meinv.getAvailableItems( new ItemList() ).isEmpty(); + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + if ( input == null ) + return null; + if ( input.getStackSize() == 0 ) + return null; + + if ( isBlackListed( input ) || CellType.isBlackListed( i, input ) ) + return input; + + ItemStack sharedItemStack = input.getItemStack(); + + if ( CellInventory.isStorageCell( sharedItemStack ) ) + { + IMEInventory meinv = getCell( sharedItemStack ); + if ( meinv != null && !isEmpty( meinv ) ) + return input; + } + + IAEItemStack l = getCellItems().findPrecise( input ); + if ( l != null ) + { + long remainingItemSlots = remainingItemCount(); + if ( remainingItemSlots < 0 ) + return input; + + if ( input.getStackSize() > remainingItemSlots ) + { + IAEItemStack r = input.copy(); + r.setStackSize( r.getStackSize() - remainingItemSlots ); + if ( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + remainingItemSlots ); + updateItemCount( remainingItemSlots ); + saveChanges(); + } + return r; + } + else + { + if ( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + input.getStackSize() ); + updateItemCount( input.getStackSize() ); + saveChanges(); + } + return null; + } + } + + if ( canHoldNewItem() ) // room for new type, and for at least one item! + { + int remainingItemCount = (int) remainingItemCount() - BytesPerType() * 8; + if ( remainingItemCount > 0 ) + { + if ( input.getStackSize() > remainingItemCount ) + { + ItemStack toReturn = Platform.cloneItemStack( sharedItemStack ); + toReturn.stackSize = sharedItemStack.stackSize - remainingItemCount; + if ( mode == Actionable.MODULATE ) + { + ItemStack toWrite = Platform.cloneItemStack( sharedItemStack ); + toWrite.stackSize = remainingItemCount; + + cellItems.add( AEItemStack.create( toWrite ) ); + updateItemCount( toWrite.stackSize ); + + saveChanges(); + } + return AEItemStack.create( toReturn ); + } + + if ( mode == Actionable.MODULATE ) + { + updateItemCount( input.getStackSize() ); + cellItems.add( input ); + saveChanges(); + } + + return null; + } + } + + return input; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + if ( request == null ) + return null; + + ItemStack sharedItem = request.getItemStack(); + int size = sharedItem.stackSize; + + IAEItemStack Results = null; + + IAEItemStack l = getCellItems().findPrecise( request ); + if ( l != null ) + { + Results = l.copy(); + + if ( l.getStackSize() <= size ) + { + Results.setStackSize( l.getStackSize() ); + if ( mode == Actionable.MODULATE ) + { + updateItemCount( -l.getStackSize() ); + l.setStackSize( 0 ); + saveChanges(); + } + } + else + { + Results.setStackSize( size ); + if ( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() - size ); + updateItemCount( -size ); + saveChanges(); + } + } + } + + return Results; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + for (IAEItemStack i : getCellItems()) + out.add( i ); + + return out; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + public double getIdleDrain() + { + return CellType.getIdleDrain(); + } + +} diff --git a/me/storage/CellInventoryHandler.java b/me/storage/CellInventoryHandler.java new file mode 100644 index 00000000..0479b20f --- /dev/null +++ b/me/storage/CellInventoryHandler.java @@ -0,0 +1,25 @@ +package appeng.me.storage; + +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEItemStack; +import appeng.util.Platform; + +public class CellInventoryHandler extends MEInventoryHandler +{ + + NBTTagCompound openNbtData() + { + return Platform.openNbtData( getCellInv().i ); + } + + public CellInventory getCellInv() + { + return (CellInventory) (this.internal instanceof CellInventory ? this.internal : null); + } + + CellInventoryHandler(IMEInventory c) { + super( c ); + } + +} diff --git a/me/storage/CreativeCellInventory.java b/me/storage/CreativeCellInventory.java new file mode 100644 index 00000000..d9555db0 --- /dev/null +++ b/me/storage/CreativeCellInventory.java @@ -0,0 +1,118 @@ +package appeng.me.storage; + +import net.minecraft.item.ItemStack; +import appeng.api.config.Actionable; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.IStorageCell; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.data.IAEItemStack; +import appeng.util.Platform; +import appeng.util.item.ItemList; + +public class CreativeCellInventory extends CellInventory implements IStorageCell +{ + + ItemList itemListCache; + + public static IMEInventoryHandler getCell(ItemStack o) + { + try + { + return new CellInventoryHandler( new CreativeCellInventory( o ) ); + } + catch (AppEngException e) + { + } + + return null; + } + + protected CreativeCellInventory(ItemStack o) throws AppEngException { + super( Platform.openNbtData( o ) ); + + if ( MAX_ITEM_TYPES > 63 ) + MAX_ITEM_TYPES = 63; + if ( MAX_ITEM_TYPES < 1 ) + MAX_ITEM_TYPES = 1; + + storedItems = tagCompound.getShort( ITEM_TYPE_TAG ); + storedItemCount = tagCompound.getInteger( ITEM_COUNT_TAG ); + cellItems = null; + } + + @Override + public boolean isStorageCell(ItemStack i) + { + return true; + } + + @Override + public int getBytes(ItemStack cellItem) + { + return 0; + } + + @Override + public int BytePerType(ItemStack iscellItem) + { + return 8; + } + + @Override + public int getTotalTypes(ItemStack cellItem) + { + return 63; + } + + @Override + public boolean isBlackListed(ItemStack cellItem, IAEItemStack requsetedAddition) + { + return false; + } + + @Override + public boolean storableInStorageCell() + { + return false; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + IAEItemStack local = getCellItems().findPrecise( input ); + if ( local == null ) + return input; + + return null; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + IAEItemStack local = getCellItems().findPrecise( request ); + if ( local == null ) + return null; + + return request.copy(); + } + + @Override + ItemList getCellItems() + { + if ( itemListCache != null ) + return itemListCache; + + ItemList list = new ItemList(); + CellInventoryHandler handler = new CellInventoryHandler( this ); + + for (IAEItemStack is : handler.myPartitionList.getItems()) + { + IAEItemStack b = is.copy(); + b.setStackSize( Integer.MAX_VALUE ); + list.add( b ); + } + + return itemListCache = list; + } + +} diff --git a/me/storage/MEIInventoryWrapper.java b/me/storage/MEIInventoryWrapper.java new file mode 100644 index 00000000..fca65b93 --- /dev/null +++ b/me/storage/MEIInventoryWrapper.java @@ -0,0 +1,196 @@ +package appeng.me.storage; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; + +public class MEIInventoryWrapper implements IMEInventory +{ + + protected IInventory target; + protected InventoryAdaptor adaptor; + + public MEIInventoryWrapper(IInventory m, InventoryAdaptor ia) { + target = m; + adaptor = ia; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public IAEItemStack injectItems(IAEItemStack iox, Actionable mode) + { + ItemStack input = iox.getItemStack(); + + if ( adaptor != null ) + { + ItemStack is = mode == Actionable.SIMULATE ? adaptor.simulateAdd( input ) : adaptor.addItems( input ); + if ( is == null ) + return null; + return AEItemStack.create( is ); + } + + ItemStack out = Platform.cloneItemStack( input ); + + if ( mode == Actionable.MODULATE ) // absolutely no need for a first run in simulate mode. + { + for (int x = 0; x < target.getSizeInventory(); x++) + { + ItemStack t = target.getStackInSlot( x ); + + if ( Platform.isSameItem( t, input ) ) + { + int oriStack = t.stackSize; + t.stackSize += out.stackSize; + + target.setInventorySlotContents( x, t ); + + if ( t.stackSize > target.getInventoryStackLimit() ) + { + t.stackSize = target.getInventoryStackLimit(); + } + + if ( t.stackSize > t.getMaxStackSize() ) + { + t.stackSize = t.getMaxStackSize(); + } + + out.stackSize -= t.stackSize - oriStack; + + if ( out.stackSize <= 0 ) + { + return null; + } + } + } + } + + for (int x = 0; x < target.getSizeInventory(); x++) + { + ItemStack t = target.getStackInSlot( x ); + + if ( t == null ) + { + t = Platform.cloneItemStack( input ); + t.stackSize = out.stackSize; + + if ( t.stackSize > target.getInventoryStackLimit() ) + { + t.stackSize = target.getInventoryStackLimit(); + } + + out.stackSize -= t.stackSize; + if ( mode == Actionable.MODULATE ) + target.setInventorySlotContents( x, t ); + + if ( out.stackSize <= 0 ) + { + return null; + } + } + } + + return AEItemStack.create( out ); + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + ItemStack Gathered = null; + ItemStack Req = request.getItemStack(); + + int request_stackSize = Req.stackSize; + + if ( request_stackSize > Req.getMaxStackSize() ) + { + request_stackSize = Req.getMaxStackSize(); + } + + Req.stackSize = request_stackSize; + + if ( adaptor != null ) + { + Gathered = adaptor.removeItems( Req.stackSize, Req, null ); + } + else + { + Gathered = request.getItemStack(); + Gathered.stackSize = 0; + + // try to find matching inventories that already have it... + for (int x = 0; x < target.getSizeInventory(); x++) + { + ItemStack sub = target.getStackInSlot( x ); + + if ( Platform.isSameItem( sub, Req ) ) + { + int reqNum = Req.stackSize; + + if ( reqNum > sub.stackSize ) + { + reqNum = Req.stackSize; + } + + ItemStack retrieved = null; + + if ( sub.stackSize < Req.stackSize ) + { + retrieved = Platform.cloneItemStack( sub ); + sub.stackSize = 0; + } + else + { + retrieved = sub.splitStack( Req.stackSize ); + } + + if ( sub.stackSize <= 0 ) + target.setInventorySlotContents( x, null ); + else + target.setInventorySlotContents( x, sub ); + + if ( retrieved != null ) + { + Gathered.stackSize += retrieved.stackSize; + Req.stackSize -= retrieved.stackSize; + } + + if ( request_stackSize == Gathered.stackSize ) + { + return AEItemStack.create( Gathered ); + } + } + } + + if ( Gathered.stackSize == 0 ) + { + return null; + } + + } + + return AEItemStack.create( Gathered ); + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + for (int x = 0; x < target.getSizeInventory(); x++) + { + out.addStorage( AEItemStack.create( target.getStackInSlot( x ) ) ); + } + + return out; + } + +} diff --git a/me/storage/MEInventoryHandler.java b/me/storage/MEInventoryHandler.java new file mode 100644 index 00000000..14ca4ee3 --- /dev/null +++ b/me/storage/MEInventoryHandler.java @@ -0,0 +1,102 @@ +package appeng.me.storage; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.IncludeExclude; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; +import appeng.util.prioitylist.DefaultPriorityList; +import appeng.util.prioitylist.IPartitionList; + +public class MEInventoryHandler> implements IMEInventoryHandler +{ + + final protected IMEMonitor monitor; + final protected IMEInventoryHandler internal; + + public int myPriority = 0; + public IncludeExclude myWhitelist = IncludeExclude.WHITELIST; + public AccessRestriction myAccess = AccessRestriction.READ_WRITE; + public IPartitionList myPartitionList = new DefaultPriorityList(); + + public MEInventoryHandler(IMEInventory i) { + if ( i instanceof IMEInventoryHandler ) + internal = (IMEInventoryHandler) i; + else + internal = new MEPassthru( i ); + + monitor = internal instanceof IMEMonitor ? (IMEMonitor) internal : null; + } + + @Override + public T injectItems(T input, Actionable type) + { + if ( !this.canAccept( input ) ) + return input; + + return internal.injectItems( input, type ); + } + + @Override + public T extractItems(T request, Actionable type) + { + return internal.extractItems( request, type ); + } + + @Override + public IItemList getAvailableItems(IItemList out) + {/* + * if ( monitor != null ) { for (T is : monitor.getStorageList()) out.add( is ); + * + * return out; } else + */ + return internal.getAvailableItems( out ); + } + + @Override + public StorageChannel getChannel() + { + return internal.getChannel(); + } + + @Override + public AccessRestriction getAccess() + { + return myAccess.restrictPermissions( internal.getAccess() ); + } + + @Override + public boolean isPrioritized(T input) + { + if ( myWhitelist == IncludeExclude.WHITELIST ) + return myPartitionList.isListed( input ) || internal.isPrioritized( input ); + return false; + } + + @Override + public boolean canAccept(T input) + { + if ( myWhitelist == IncludeExclude.BLACKLIST && myPartitionList.isListed( input ) ) + return false; + if ( myPartitionList.isEmpty() || myWhitelist == IncludeExclude.BLACKLIST ) + return internal.canAccept( input ); + return myPartitionList.isListed( input ) && internal.canAccept( input ); + } + + @Override + public int getPriority() + { + return myPriority; + } + + @Override + public int getSlot() + { + return internal.getSlot(); + } + +} diff --git a/me/storage/MEMonitorIInventory.java b/me/storage/MEMonitorIInventory.java new file mode 100644 index 00000000..d1ec9ae8 --- /dev/null +++ b/me/storage/MEMonitorIInventory.java @@ -0,0 +1,257 @@ +package appeng.me.storage; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.TreeMap; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMontorHandlerReciever; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.core.AELog; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.inv.ItemSlot; +import appeng.util.item.AEItemStack; +import appeng.util.item.ItemList; + +public class MEMonitorIInventory implements IMEInventory, IMEMonitor +{ + + class CachedItemStack + { + + public CachedItemStack(ItemStack is) { + if ( is == null ) + { + itemStack = null; + aeStack = null; + } + else + { + itemStack = is.copy(); + aeStack = AEApi.instance().storage().createItemStack( is ); + } + } + + final ItemStack itemStack; + final IAEItemStack aeStack; + }; + + final IInventory internal; + final ForgeDirection side; + final InventoryAdaptor adaptor; + + final TreeMap memory; + final IItemList list = new ItemList(); + final HashMap, Object> listeners = new HashMap(); + + @Override + public void addListener(IMEMontorHandlerReciever l, Object verificationToken) + { + listeners.put( l, verificationToken ); + } + + @Override + public void removeListener(IMEMontorHandlerReciever l) + { + listeners.remove( l ); + } + + public MEMonitorIInventory(IInventory inv, ForgeDirection dir) { + adaptor = InventoryAdaptor.getAdaptor( inv, dir ); + memory = new TreeMap(); + internal = inv; + side = dir; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable type) + { + ItemStack out = null; + + if ( type == Actionable.SIMULATE ) + out = adaptor.simulateAdd( input.getItemStack() ); + else + out = adaptor.addItems( input.getItemStack() ); + + if ( out == null ) + return null; + + // better then doing construction from scratch :3 + IAEItemStack o = input.copy(); + o.setStackSize( out.stackSize ); + return o; + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.READ_WRITE; + } + + @Override + public boolean isPrioritized(IAEItemStack input) + { + return false; + } + + @Override + public boolean canAccept(IAEItemStack input) + { + return true; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + + @Override + public IItemList getStorageList() + { + for (IAEItemStack is : list) + AELog.info( "sl: " + is.getItemStack().getUnlocalizedName() + " @ " + is.getStackSize() ); + + return list; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + for (ItemSlot is : adaptor) + out.addStorage( AEItemStack.create( is.itemStack ) ); + + return out; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable type) + { + ItemStack out = null; + + if ( type == Actionable.SIMULATE ) + out = adaptor.simulateRemove( (int) request.getStackSize(), request.getItemStack(), null ); + else + out = adaptor.removeItems( (int) request.getStackSize(), request.getItemStack(), null ); + + if ( out == null ) + return null; + + // better then doing construction from scratch :3 + IAEItemStack o = request.copy(); + o.setStackSize( out.stackSize ); + return o; + } + + public TickRateModulation onTick() + { + boolean changed = false; + + list.resetStatus(); + for (ItemSlot is : adaptor) + { + CachedItemStack old = memory.get( is.slot ); + ItemStack newIS = is == null ? null : is.itemStack; + ItemStack oldIS = old == null ? null : old.itemStack; + + if ( isDiffrent( newIS, oldIS ) ) + { + CachedItemStack cis = new CachedItemStack( is.itemStack ); + memory.put( is.slot, cis ); + + if ( old != null && old.aeStack != null ) + { + old.aeStack.setStackSize( -old.aeStack.getStackSize() ); + postDiffrence( old.aeStack ); + } + + if ( cis != null && cis.aeStack != null ) + { + postDiffrence( cis.aeStack ); + list.add( cis.aeStack ); + } + + changed = true; + } + else if ( is != null ) + { + int newSize = (newIS == null ? 0 : newIS.stackSize); + int diff = newSize - (oldIS == null ? 0 : oldIS.stackSize); + + IAEItemStack stack = (old == null || old.aeStack == null ? AEApi.instance().storage().createItemStack( newIS ) : old.aeStack.copy()); + if ( stack != null ) + { + stack.setStackSize( newSize ); + list.add( stack ); + } + + if ( diff != 0 && stack != null ) + { + CachedItemStack cis = new CachedItemStack( is.itemStack ); + memory.put( is.slot, cis ); + + IAEItemStack a = stack.copy(); + a.setStackSize( diff ); + postDiffrence( a ); + changed = true; + } + } + } + + return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; + } + + private boolean isDiffrent(ItemStack a, ItemStack b) + { + if ( a == b && b == null ) + return false; + + if ( (a == null && b != null) || (a != null && b == null) ) + return true; + + return !Platform.isSameItemPrecise( a, b ); + } + + private void postDiffrence(IAEItemStack a) + { + AELog.info( a.getItemStack().getUnlocalizedName() + " @ " + a.getStackSize() ); + if ( a != null ) + { + Iterator, Object>> i = listeners.entrySet().iterator(); + while (i.hasNext()) + { + Entry, Object> l = i.next(); + IMEMontorHandlerReciever key = l.getKey(); + if ( key.isValid( l.getValue() ) ) + key.postChange( a ); + else + i.remove(); + } + } + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + +} diff --git a/me/storage/MEMonitorPassthu.java b/me/storage/MEMonitorPassthu.java new file mode 100644 index 00000000..d3e083fa --- /dev/null +++ b/me/storage/MEMonitorPassthu.java @@ -0,0 +1,88 @@ +package appeng.me.storage; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; + +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMontorHandlerReciever; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; +import appeng.util.Platform; +import appeng.util.item.ItemList; + +public class MEMonitorPassthu> extends MEPassthru implements IMEMonitor, IMEMontorHandlerReciever +{ + + HashMap, Object> listeners = new HashMap(); + IMEMonitor monitor; + + public MEMonitorPassthu(IMEInventory i) { + super( i ); + if ( i instanceof IMEMonitor ) + monitor = (IMEMonitor) i; + } + + @Override + public void setInternal(IMEInventory i) + { + if ( monitor != null ) + monitor.removeListener( this ); + + monitor = null; + IItemList before = getInternal() == null ? new ItemList() : getInternal().getAvailableItems( new ItemList() ); + + super.setInternal( i ); + if ( i instanceof IMEMonitor ) + monitor = (IMEMonitor) i; + + IItemList after = getInternal() == null ? new ItemList() : getInternal().getAvailableItems( new ItemList() ); + + if ( monitor != null ) + monitor.addListener( this, monitor ); + + Platform.postListChanges( before, after, this ); + } + + @Override + public void addListener(IMEMontorHandlerReciever l, Object verificationToken) + { + listeners.put( l, verificationToken ); + } + + @Override + public void removeListener(IMEMontorHandlerReciever l) + { + listeners.remove( l ); + } + + @Override + public IItemList getStorageList() + { + if ( monitor == null ) + return getInternal().getAvailableItems( new ItemList() ); + return monitor.getStorageList(); + } + + @Override + public boolean isValid(Object verificationToken) + { + return verificationToken == monitor; + } + + @Override + public void postChange(T change) + { + Iterator, Object>> i = listeners.entrySet().iterator(); + while (i.hasNext()) + { + Entry, Object> e = i.next(); + IMEMontorHandlerReciever recv = e.getKey(); + if ( recv.isValid( e.getValue() ) ) + recv.postChange( change ); + else + i.remove(); + } + } +} diff --git a/me/storage/MEPassthru.java b/me/storage/MEPassthru.java new file mode 100644 index 00000000..25a6dd02 --- /dev/null +++ b/me/storage/MEPassthru.java @@ -0,0 +1,84 @@ +package appeng.me.storage; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +public class MEPassthru> implements IMEInventoryHandler +{ + + private IMEInventory internal; + + protected IMEInventory getInternal() + { + return internal; + } + + public MEPassthru(IMEInventory i) { + setInternal( i ); + } + + public void setInternal(IMEInventory i) + { + internal = i; + } + + @Override + public T injectItems(T input, Actionable type) + { + return internal.injectItems( input, type ); + } + + @Override + public T extractItems(T request, Actionable type) + { + return internal.extractItems( request, type ); + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + return internal.getAvailableItems( out ); + } + + @Override + public StorageChannel getChannel() + { + return internal.getChannel(); + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.READ_WRITE; + } + + @Override + public boolean isPrioritized(T input) + { + return false; + } + + @Override + public boolean canAccept(T input) + { + return true; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + +} diff --git a/me/storage/NetworkInventoryHandler.java b/me/storage/NetworkInventoryHandler.java new file mode 100644 index 00000000..6d9a7aeb --- /dev/null +++ b/me/storage/NetworkInventoryHandler.java @@ -0,0 +1,213 @@ +package appeng.me.storage; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map.Entry; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +import com.google.common.collect.TreeMultimap; + +public class NetworkInventoryHandler> implements IMEInventoryHandler +{ + + private final static Comparator prioritySorter = new Comparator() { + + @Override + public int compare(Integer o1, Integer o2) + { + return o1 - o2; + } + + }; + + private final static Comparator hashSorter = new Comparator() { + + @Override + public int compare(IMEInventoryHandler o1, IMEInventoryHandler o2) + { + return o1.hashCode() - o2.hashCode(); + } + + }; + + final StorageChannel myChannel; + final TreeMultimap> prorityInventory; + + public NetworkInventoryHandler(StorageChannel chan) { + myChannel = chan; + prorityInventory = TreeMultimap.create( prioritySorter, hashSorter ); + } + + public void addNewStorage(IMEInventoryHandler h) + { + prorityInventory.put( h.getPriority(), h ); + } + + static int currentPass = 0; + int myPass = 0; + final static public LinkedList depth = new LinkedList(); + + private boolean diveList(NetworkInventoryHandler networkInventoryHandler) + { + if ( depth.contains( networkInventoryHandler ) ) + return true; + + depth.push( this ); + return false; + } + + private boolean diveIteration(NetworkInventoryHandler networkInventoryHandler) + { + if ( depth.isEmpty() ) + { + currentPass++; + myPass = currentPass; + } + else + { + if ( currentPass == myPass ) + return true; + else + myPass = currentPass; + } + + depth.push( this ); + return false; + } + + private void surface(NetworkInventoryHandler networkInventoryHandler) + { + Object last = depth.pop(); + if ( last != this ) + throw new RuntimeException( "Invalid Access to Networked Storage API detected." ); + } + + @Override + public T injectItems(T input, Actionable type) + { + if ( diveList( this ) ) + return input; + + Iterator>>> i = prorityInventory.asMap().entrySet().iterator(); + + while (i.hasNext()) + { + Entry>> invList = i.next(); + + Iterator> ii = invList.getValue().iterator(); + while (ii.hasNext() && input != null) + { + IMEInventoryHandler inv = ii.next(); + + if ( inv.canAccept( input ) && (inv.extractItems( input, Actionable.SIMULATE ) != null || inv.isPrioritized( input )) ) + input = inv.injectItems( input, type ); + } + + ii = invList.getValue().iterator(); + while (ii.hasNext() && input != null) + { + IMEInventoryHandler inv = ii.next(); + if ( inv.canAccept( input ) ) + input = inv.injectItems( input, type ); + } + } + + surface( this ); + + return input; + } + + @Override + public T extractItems(T request, Actionable mode) + { + if ( diveList( this ) ) + return null; + + Iterator>>> i = prorityInventory.asMap().descendingMap().entrySet().iterator(); + + T output = request.copy(); + request = request.copy(); + output.setStackSize( 0 ); + long req = request.getStackSize(); + + while (i.hasNext()) + { + Entry>> invList = i.next(); + + Iterator> ii = invList.getValue().iterator(); + while (ii.hasNext() && output.getStackSize() < req) + { + IMEInventoryHandler inv = ii.next(); + + request.setStackSize( req - output.getStackSize() ); + output.add( inv.extractItems( request, mode ) ); + } + } + + surface( this ); + + if ( output.getStackSize() <= 0 ) + return null; + + return output; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + if ( diveIteration( this ) ) + return out; + + for (Entry> h : prorityInventory.entries()) + out = h.getValue().getAvailableItems( out ); + + surface( this ); + + return out; + } + + @Override + public StorageChannel getChannel() + { + return myChannel; + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.READ_WRITE; + } + + @Override + public boolean isPrioritized(T input) + { + return false; + } + + @Override + public boolean canAccept(T input) + { + return true; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + +} diff --git a/me/storage/NullInventory.java b/me/storage/NullInventory.java new file mode 100644 index 00000000..46c6b965 --- /dev/null +++ b/me/storage/NullInventory.java @@ -0,0 +1,67 @@ +package appeng.me.storage; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +public class NullInventory> implements IMEInventoryHandler +{ + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public T injectItems(T input, Actionable mode) + { + return input; + } + + @Override + public T extractItems(T request, Actionable mode) + { + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + return out; + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.READ; + } + + @Override + public boolean isPrioritized(T input) + { + return false; + } + + @Override + public boolean canAccept(T input) + { + return false; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + +} diff --git a/me/storage/VoidFluidInventory.java b/me/storage/VoidFluidInventory.java new file mode 100644 index 00000000..b42f6168 --- /dev/null +++ b/me/storage/VoidFluidInventory.java @@ -0,0 +1,76 @@ +package appeng.me.storage; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.tile.misc.TileCondenser; + +public class VoidFluidInventory implements IMEInventoryHandler +{ + + TileCondenser target; + + public VoidFluidInventory(TileCondenser te) { + target = te; + } + + @Override + public IAEFluidStack injectItems(IAEFluidStack input, Actionable mode) + { + if ( input != null ) + target.addPower( (double) input.getStackSize() / 1000.0 ); + return null; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.FLUIDS; + } + + @Override + public IAEFluidStack extractItems(IAEFluidStack request, Actionable mode) + { + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + return out; + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.WRITE; + } + + @Override + public boolean isPrioritized(IAEFluidStack input) + { + return false; + } + + @Override + public boolean canAccept(IAEFluidStack input) + { + return true; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + +} diff --git a/me/storage/VoidItemInventory.java b/me/storage/VoidItemInventory.java new file mode 100644 index 00000000..8ea739e8 --- /dev/null +++ b/me/storage/VoidItemInventory.java @@ -0,0 +1,76 @@ +package appeng.me.storage; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.tile.misc.TileCondenser; + +public class VoidItemInventory implements IMEInventoryHandler +{ + + TileCondenser target; + + public VoidItemInventory(TileCondenser te) { + target = te; + } + + @Override + public IAEItemStack injectItems(IAEItemStack input, Actionable mode) + { + if ( input != null ) + target.addPower( input.getStackSize() ); + return null; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public IAEItemStack extractItems(IAEItemStack request, Actionable mode) + { + return null; + } + + @Override + public IItemList getAvailableItems(IItemList out) + { + return out; + } + + @Override + public AccessRestriction getAccess() + { + return AccessRestriction.WRITE; + } + + @Override + public boolean isPrioritized(IAEItemStack input) + { + return false; + } + + @Override + public boolean canAccept(IAEItemStack input) + { + return true; + } + + @Override + public int getPriority() + { + return 0; + } + + @Override + public int getSlot() + { + return 0; + } + +} diff --git a/parts/AEBasePart.java b/parts/AEBasePart.java new file mode 100644 index 00000000..482ee006 --- /dev/null +++ b/parts/AEBasePart.java @@ -0,0 +1,240 @@ +package appeng.parts; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.IGridProxyable; +import appeng.parts.networking.PartCable; + +public class AEBasePart implements IPart, IGridProxyable, IGridHost +{ + + protected AENetworkProxy proxy = new AENetworkProxy( this, "part", this instanceof PartCable ); + protected TileEntity tile = null; + protected IPartHost host = null; + protected ForgeDirection side = null; + + protected final ItemStack is; + + public AEBasePart(Class c, ItemStack is) { + this.is = is; + proxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setBounds( 1, 1, 1, 15, 15, 15 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 1, 1, 1, 15, 15, 15 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setBounds( 1, 1, 1, 15, 15, 15 ); + rh.renderBlock( x, y, z, renderer ); + } + + @Override + public void renderDynamic(double x, double y, double z, IPartRenderHelper rh, RenderBlocks renderer) + { + + } + + @Override + public ItemStack getItemStack(boolean wrenched) + { + return is; + } + + @Override + public boolean isSolid() + { + return false; + } + + @Override + public void onNeighborChanged() + { + + } + + @Override + public boolean canConnectRedstone() + { + return false; + } + + @Override + public void readFromNBT(NBTTagCompound extra) + { + proxy.readFromNBT( extra ); + } + + @Override + public void writeToNBT(NBTTagCompound extra) + { + proxy.writeToNBT( extra ); + } + + @Override + public int isProvidingStrongPower() + { + return 0; + } + + @Override + public int isProvidingWeakPower() + { + return 0; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + return false; + } + + @Override + public IGridNode getGridNode() + { + return proxy.getNode(); + } + + @Override + public void onEntityCollision(Entity entity) + { + + } + + @Override + public void removeFromWorld() + { + proxy.invalidate(); + } + + @Override + public void addToWorld() + { + proxy.onReady(); + } + + @Override + public void setPartHostInfo(ForgeDirection side, IPartHost host, TileEntity tile) + { + this.side = side; + this.tile = tile; + this.host = host; + } + + public IPartHost getHost() + { + return host; + } + + @Override + public IGridNode getExternalFacingNode() + { + return null; + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return proxy.getNode(); + } + + protected AEColor getColor() + { + if ( getHost() == null ) + return AEColor.Transparent; + return getHost().getColor(); + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( tile ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + + } + + @Override + public void randomDisplayTick(World world, int x, int y, int z, Random r) + { + + } + + @Override + public int getLightLevel() + { + return 0; + } + + @Override + public boolean onActivate(EntityPlayer player, Vec3 pos) + { + return false; + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.GLASS; + } + + @Override + public void getDrops(List drops, boolean wrenched) + { + + } + + @Override + public int cableConnectionRenderTo() + { + return 3; + } + + @Override + public void gridChanged() + { + + } + +} \ No newline at end of file diff --git a/parts/BusCollisionHelper.java b/parts/BusCollisionHelper.java new file mode 100644 index 00000000..4184d564 --- /dev/null +++ b/parts/BusCollisionHelper.java @@ -0,0 +1,133 @@ +package appeng.parts; + +import java.util.List; + +import net.minecraft.util.AxisAlignedBB; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPartCollsionHelper; + +public class BusCollisionHelper implements IPartCollsionHelper +{ + + final List boxes; + + final private ForgeDirection x; + final private ForgeDirection y; + final private ForgeDirection z; + + public BusCollisionHelper(List boxes, ForgeDirection x, ForgeDirection y, ForgeDirection z) { + this.boxes = boxes; + this.x = x; + this.y = y; + this.z = z; + } + + public BusCollisionHelper(List boxes, ForgeDirection s) { + this.boxes = boxes; + + switch (s) + { + case DOWN: + x = ForgeDirection.EAST; + y = ForgeDirection.NORTH; + z = ForgeDirection.DOWN; + break; + case UP: + x = ForgeDirection.EAST; + y = ForgeDirection.SOUTH; + z = ForgeDirection.UP; + break; + case EAST: + x = ForgeDirection.SOUTH; + y = ForgeDirection.UP; + z = ForgeDirection.EAST; + break; + case WEST: + x = ForgeDirection.NORTH; + y = ForgeDirection.UP; + z = ForgeDirection.WEST; + break; + case NORTH: + x = ForgeDirection.WEST; + y = ForgeDirection.UP; + z = ForgeDirection.NORTH; + break; + case SOUTH: + x = ForgeDirection.EAST; + y = ForgeDirection.UP; + z = ForgeDirection.SOUTH; + break; + case UNKNOWN: + default: + x = ForgeDirection.EAST; + y = ForgeDirection.UP; + z = ForgeDirection.SOUTH; + break; + } + } + + @Override + public void addBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) + { + minX /= 16.0; + minY /= 16.0; + minZ /= 16.0; + maxX /= 16.0; + maxY /= 16.0; + maxZ /= 16.0; + + double aX = minX * x.offsetX + minY * y.offsetX + minZ * z.offsetX; + double aY = minX * x.offsetY + minY * y.offsetY + minZ * z.offsetY; + double aZ = minX * x.offsetZ + minY * y.offsetZ + minZ * z.offsetZ; + + double bX = maxX * x.offsetX + maxY * y.offsetX + maxZ * z.offsetX; + double bY = maxX * x.offsetY + maxY * y.offsetY + maxZ * z.offsetY; + double bZ = maxX * x.offsetZ + maxY * y.offsetZ + maxZ * z.offsetZ; + + if ( x.offsetX + y.offsetX + z.offsetX < 0 ) + { + aX += 1; + bX += 1; + } + + if ( x.offsetY + y.offsetY + z.offsetY < 0 ) + { + aY += 1; + bY += 1; + } + + if ( x.offsetZ + y.offsetZ + z.offsetZ < 0 ) + { + aZ += 1; + bZ += 1; + } + + minX = Math.min( aX, bX ); + minY = Math.min( aY, bY ); + minZ = Math.min( aZ, bZ ); + maxX = Math.max( aX, bX ); + maxY = Math.max( aY, bY ); + maxZ = Math.max( aZ, bZ ); + + boxes.add( AxisAlignedBB.getBoundingBox( minX, minY, minZ, maxX, maxY, maxZ ) ); + } + + @Override + public ForgeDirection getWorldX() + { + return x; + } + + @Override + public ForgeDirection getWorldY() + { + return y; + } + + @Override + public ForgeDirection getWorldZ() + { + return z; + } + +} diff --git a/parts/CableBusContainer.java b/parts/CableBusContainer.java new file mode 100644 index 00000000..c78b40d1 --- /dev/null +++ b/parts/CableBusContainer.java @@ -0,0 +1,896 @@ +package appeng.parts; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.implementations.IPartCable; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IFacadePart; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartItem; +import appeng.api.parts.SelectedPart; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.client.render.BusRenderHelper; +import appeng.client.render.BusRenderer; +import appeng.client.render.RenderBlocksWorkaround; +import appeng.facade.FacadeContainer; +import appeng.helpers.AEMultiTile; +import appeng.me.GridConnection; +import appeng.util.Platform; + +public class CableBusContainer implements AEMultiTile +{ + + private IPartCable center; + private IPart sides[] = new IPart[6]; + private FacadeContainer fc = new FacadeContainer(); + + public boolean hasRedstone = false; + public IPartHost tcb; + + boolean inWorld = false; + + public void setHost(IPartHost host) + { + tcb.clearContainer(); + tcb = host; + } + + public CableBusContainer(IPartHost host) { + tcb = host; + } + + @Override + public IPart getPart(ForgeDirection side) + { + if ( side == ForgeDirection.UNKNOWN ) + return center; + return sides[side.ordinal()]; + } + + @Override + public void removePart(ForgeDirection side) + { + if ( side == ForgeDirection.UNKNOWN ) + { + if ( center != null ) + center.removeFromWorld(); + center = null; + } + else + { + if ( sides[side.ordinal()] != null ) + sides[side.ordinal()].removeFromWorld(); + sides[side.ordinal()] = null; + } + + updateConnections(); + markForUpdate(); + PartChanged(); + } + + /** + * use for FMP + */ + public void updateConnections() + { + if ( center != null ) + { + EnumSet sides = EnumSet.allOf( ForgeDirection.class ); + + for (ForgeDirection s : ForgeDirection.VALID_DIRECTIONS) + { + if ( getPart( s ) != null || isBlocked( s ) ) + sides.remove( s ); + } + + center.setValidSides( sides ); + IGridNode n = center.getGridNode(); + if ( n != null ) + n.updateState(); + } + } + + @Override + public boolean canAddPart(ItemStack is, ForgeDirection side) + { + if ( is.getItem() instanceof IPartItem ) + { + IPartItem bi = (IPartItem) is.getItem(); + + is = is.copy(); + is.stackSize = 1; + + IPart bp = bi.createPartFromItemStack( is ); + if ( bp instanceof IPartCable ) + { + return getPart( ForgeDirection.UNKNOWN ) == null; + } + else if ( !(bp instanceof IPartCable) && side != ForgeDirection.UNKNOWN ) + { + return getPart( side ) == null; + } + } + return false; + } + + @Override + public ForgeDirection addPart(ItemStack is, ForgeDirection side) + { + if ( canAddPart( is, side ) ) + { + if ( is.getItem() instanceof IPartItem ) + { + IPartItem bi = (IPartItem) is.getItem(); + + is = is.copy(); + is.stackSize = 1; + + IPart bp = bi.createPartFromItemStack( is ); + if ( bp instanceof IPartCable ) + { + if ( getPart( ForgeDirection.UNKNOWN ) != null ) + return null; + + center = (IPartCable) bp; + bp.setPartHostInfo( ForgeDirection.UNKNOWN, this, tcb.getTile() ); + + if ( inWorld ) + bp.addToWorld(); + + IGridNode cn = center.getGridNode(); + if ( cn != null ) + { + for (ForgeDirection ins : ForgeDirection.VALID_DIRECTIONS) + { + IPart sbp = getPart( ins ); + if ( sbp != null ) + { + IGridNode sn = sbp.getGridNode(); + if ( sn != null && cn != null ) + new GridConnection( (IGridNode) cn, (IGridNode) sn, ForgeDirection.UNKNOWN ); + } + } + } + + updateConnections(); + markForUpdate(); + PartChanged(); + return ForgeDirection.UNKNOWN; + } + else if ( !(bp instanceof IPartCable) && side != ForgeDirection.UNKNOWN ) + { + sides[side.ordinal()] = bp; + bp.setPartHostInfo( side, this, this.getTile() ); + + if ( inWorld ) + bp.addToWorld(); + + if ( center != null ) + { + IGridNode cn = center.getGridNode(); + IGridNode sn = bp.getGridNode(); + + if ( cn != null && sn != null ) + { + new GridConnection( (IGridNode) cn, (IGridNode) sn, ForgeDirection.UNKNOWN ); + } + } + + updateConnections(); + markForUpdate(); + PartChanged(); + return side; + } + } + } + return null; + } + + public void addToWorld() + { + inWorld = true; + + TileEntity te = getTile(); + hasRedstone = te.worldObj.isBlockIndirectlyGettingPowered( te.xCoord, te.yCoord, te.zCoord ); + + // start with the center, then install the side parts into the grid. + for (int x = 6; x >= 0; x--) + { + ForgeDirection s = ForgeDirection.getOrientation( x ); + IPart part = getPart( s ); + + if ( part != null ) + { + part.setPartHostInfo( s, this, te ); + part.addToWorld(); + + if ( s != ForgeDirection.UNKNOWN ) + { + IGridNode sn = part.getGridNode(); + if ( sn != null ) + { + // this is a really stupid if statement, why was this here? + // if ( !sn.getConnections().iterator().hasNext() ) + + IPart center = getPart( ForgeDirection.UNKNOWN ); + if ( center != null ) + { + IGridNode cn = center.getGridNode(); + if ( cn != null ) + { + AEApi.instance().createGridConnection( cn, sn ); + } + } + + } + } + } + } + } + + public void removeFromWorld() + { + inWorld = false; + + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + part.removeFromWorld(); + } + } + + public boolean canConnectRedstone(ForgeDirection side) + { + IPart part = getPart( side ); + return part != null && part.canConnectRedstone(); + } + + @Override + public IGridNode getGridNode(ForgeDirection side) + { + IPart part = getPart( side ); + if ( part != null ) + { + IGridNode n = part.getExternalFacingNode(); + if ( n != null ) + return n; + } + + if ( center != null ) + return center.getGridNode(); + + return null; + } + + public Iterable getSelectedBoundingBoxsFromPool(boolean ignoreCableConnections) + { + List boxes = new LinkedList(); + + for (ForgeDirection s : ForgeDirection.values()) + { + IPartCollsionHelper bch = new BusCollisionHelper( boxes, s ); + + IPart part = getPart( s ); + if ( part != null ) + { + if ( ignoreCableConnections && part instanceof IPartCable ) + bch.addBox( 6.0, 6.0, 6.0, 10.0, 10.0, 10.0 ); + else + part.getBoxes( bch ); + + } + + if ( !ignoreCableConnections && s != null && s != ForgeDirection.UNKNOWN ) + { + IFacadePart fp = fc.getFacade( s ); + if ( fp != null ) + fp.getBoxes( bch ); + } + } + + return boxes; + } + + public void onEntityCollision(Entity entity) + { + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + part.onEntityCollision( entity ); + } + } + + public boolean isEmpty() + { + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + return false; + + if ( s != ForgeDirection.UNKNOWN ) + { + IFacadePart fp = fc.getFacade( s ); + if ( fp != null ) + return false; + } + } + return true; + } + + public void onNeighborChanged() + { + TileEntity te = getTile(); + hasRedstone = te.worldObj.isBlockIndirectlyGettingPowered( te.xCoord, te.yCoord, te.zCoord ); + + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + part.onNeighborChanged(); + } + } + + public boolean isSolidOnSide(ForgeDirection side) + { + if ( side == null || side == ForgeDirection.UNKNOWN ) + return false; + + // facades are solid.. + IFacadePart fp = fc.getFacade( side ); + if ( fp != null ) + return true; + + // buses can be too. + IPart part = getPart( side ); + return part != null && part.isSolid(); + } + + public int isProvidingWeakPower(ForgeDirection side) + { + IPart part = getPart( side ); + return part != null ? part.isProvidingWeakPower() : 0; + } + + public int isProvidingStrongPower(ForgeDirection side) + { + IPart part = getPart( side ); + return part != null ? part.isProvidingStrongPower() : 0; + } + + public void setSide(ForgeDirection s) + { + switch (s) + { + case DOWN: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.NORTH; + BusRenderHelper.instance.az = ForgeDirection.DOWN; + break; + case UP: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.SOUTH; + BusRenderHelper.instance.az = ForgeDirection.UP; + break; + case EAST: + BusRenderHelper.instance.ax = ForgeDirection.SOUTH; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.EAST; + break; + case WEST: + BusRenderHelper.instance.ax = ForgeDirection.NORTH; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.WEST; + break; + case NORTH: + BusRenderHelper.instance.ax = ForgeDirection.WEST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.NORTH; + break; + case SOUTH: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.SOUTH; + break; + case UNKNOWN: + default: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.SOUTH; + break; + + } + } + + public void renderStatic(double x, double y, double z) + { + TileEntity te = getTile(); + RenderBlocksWorkaround renderer = BusRenderer.instance.renderer; + + if ( renderer.blockAccess == null ) + renderer.blockAccess = Minecraft.getMinecraft().theWorld; + + for (ForgeDirection s : ForgeDirection.values()) + { + setSide( s ); + + IPart part = getPart( s ); + if ( part != null ) + { + renderer.renderAllFaces = true; + part.renderStatic( te.xCoord, te.yCoord, te.zCoord, BusRenderHelper.instance, renderer ); + } + } + + if ( !fc.isEmpty() ) + { + /** + * snag list of boxes... + */ + List boxes = new ArrayList(); + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + { + setSide( s ); + BusCollisionHelper bch = new BusCollisionHelper( boxes, BusRenderHelper.instance.ax, BusRenderHelper.instance.ay, + BusRenderHelper.instance.az ); + part.getBoxes( bch ); + } + } + + for (ForgeDirection s : ForgeDirection.VALID_DIRECTIONS) + { + IFacadePart fPart = fc.getFacade( s ); + if ( fPart != null ) + { + AxisAlignedBB b = null; + AxisAlignedBB pb = fPart.getPrimaryBox(); + for (AxisAlignedBB bb : boxes) + { + if ( bb.intersectsWith( pb ) ) + { + if ( b == null ) + b = bb; + else + { + b.maxX = Math.max( b.maxX, bb.maxX ); + b.maxY = Math.max( b.maxY, bb.maxY ); + b.maxZ = Math.max( b.maxZ, bb.maxZ ); + b.minX = Math.min( b.minX, bb.minX ); + b.minY = Math.min( b.minY, bb.minY ); + b.minZ = Math.min( b.minZ, bb.minZ ); + } + } + } + + setSide( s ); + fPart.renderStatic( te.xCoord, te.yCoord, te.zCoord, BusRenderHelper.instance, renderer, fc, b, getPart( s ) == null ); + } + } + + renderer.isFacade = false; + renderer.enableAO = false; + renderer.setTexture( null ); + renderer.calculations = true; + } + } + + public void renderDynamic(double x, double y, double z) + { + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + { + switch (s) + { + case DOWN: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.NORTH; + BusRenderHelper.instance.az = ForgeDirection.DOWN; + break; + case UP: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.SOUTH; + BusRenderHelper.instance.az = ForgeDirection.UP; + break; + case EAST: + BusRenderHelper.instance.ax = ForgeDirection.SOUTH; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.EAST; + break; + case WEST: + BusRenderHelper.instance.ax = ForgeDirection.NORTH; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.WEST; + break; + case NORTH: + BusRenderHelper.instance.ax = ForgeDirection.WEST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.NORTH; + break; + case SOUTH: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.SOUTH; + break; + case UNKNOWN: + default: + BusRenderHelper.instance.ax = ForgeDirection.EAST; + BusRenderHelper.instance.ay = ForgeDirection.UP; + BusRenderHelper.instance.az = ForgeDirection.SOUTH; + break; + + } + part.renderDynamic( x, y, z, BusRenderHelper.instance, BusRenderer.instance.renderer ); + } + } + } + + public void writeToStream(DataOutputStream data) throws IOException + { + int sides = 0; + for (int x = 0; x < 7; x++) + { + IPart p = getPart( ForgeDirection.getOrientation( x ) ); + if ( p != null ) + { + sides = sides | (1 << x); + } + } + + data.writeByte( (byte) sides ); + + for (int x = 0; x < 7; x++) + { + ItemStack is = null; + IPart p = getPart( ForgeDirection.getOrientation( x ) ); + if ( p != null ) + { + is = p.getItemStack( false ); + is.setTagCompound( null ); + + data.writeShort( is.getItem().itemID ); + data.writeShort( is.getItemDamage() ); + + if ( p != null ) + p.writeToStream( data ); + } + } + + fc.writeToStream( data ); + } + + public boolean readFromStream(DataInputStream data) throws IOException + { + byte sides = data.readByte(); + + for (int x = 0; x < 7; x++) + { + ForgeDirection side = ForgeDirection.getOrientation( x ); + if ( ((sides & (1 << x)) == (1 << x)) ) + { + IPart p = getPart( side ); + + short itemID = data.readShort(); + short dmgValue = data.readShort(); + + ItemStack current = p != null ? p.getItemStack( false ) : null; + if ( current != null && current.getItem().itemID == itemID && current.getItemDamage() == dmgValue ) + p.readFromStream( data ); + else + { + removePart( side ); + side = addPart( new ItemStack( Item.itemsList[itemID], 1, dmgValue ), side ); + if ( side != null ) + { + p = getPart( side ); + p.readFromStream( data ); + } + else + throw new RuntimeException( "Invalid Stream For CableBus Container." ); + } + } + else + removePart( side ); + } + + return fc.readFromStream( data ); + } + + ForgeDirection getSide(IPart part) + { + if ( center == part ) + return ForgeDirection.UNKNOWN; + else + { + for (int x = 0; x < 6; x++) + if ( sides[x] == part ) + { + return ForgeDirection.getOrientation( x ); + } + } + throw new RuntimeException( "Uhh Bad Part on Side." ); + } + + public void writeToNBT(NBTTagCompound data) + { + for (ForgeDirection s : ForgeDirection.values()) + { + fc.writeToNBT( data ); + + IPart part = getPart( s ); + if ( part != null ) + { + NBTTagCompound def = new NBTTagCompound(); + part.getItemStack( false ).writeToNBT( def ); + + NBTTagCompound extra = new NBTTagCompound(); + part.writeToNBT( extra ); + + data.setCompoundTag( "def:" + getSide( part ).ordinal(), def ); + data.setCompoundTag( "extra:" + getSide( part ).ordinal(), extra ); + } + } + } + + public void readFromNBT(NBTTagCompound data) + { + fc.readFromNBT( data ); + + for (int x = 0; x < 7; x++) + { + ForgeDirection side = ForgeDirection.getOrientation( x ); + + NBTTagCompound def = data.getCompoundTag( "def:" + side.ordinal() ); + NBTTagCompound extra = data.getCompoundTag( "extra:" + side.ordinal() ); + if ( def != null && extra != null ) + { + IPart p = getPart( side ); + ItemStack iss = ItemStack.loadItemStackFromNBT( def ); + if ( iss == null ) + continue; + + ItemStack current = p == null ? null : p.getItemStack( false ); + + if ( Platform.isSameItemType( iss, current ) ) + p.readFromNBT( extra ); + else + { + removePart( side ); + side = addPart( iss, side ); + if ( side != null ) + { + p = getPart( side ); + p.readFromNBT( extra ); + } + else + throw new RuntimeException( "Invalid NBT For CableBus Container." ); + } + } + else + removePart( side ); + } + } + + public List getDrops(List drops) + { + for (ForgeDirection s : ForgeDirection.values()) + { + IPart part = getPart( s ); + if ( part != null ) + { + drops.add( part.getItemStack( false ) ); + part.getDrops( drops, false ); + } + + if ( s != ForgeDirection.UNKNOWN ) + { + IFacadePart fp = getFacadeContainer().getFacade( s ); + if ( fp != null ) + drops.add( fp.getItemStack() ); + } + } + + return drops; + } + + @Override + public void markForUpdate() + { + tcb.markForUpdate(); + } + + @Override + public DimensionalCoord getLocation() + { + return tcb.getLocation(); + } + + @Override + public TileEntity getTile() + { + return tcb.getTile(); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + if ( center != null ) + { + IPartCable c = center; + return c.getCableConnectionType(); + } + return AECableType.NONE; + } + + @Override + public AEColor getColor() + { + if ( center != null ) + { + IPartCable c = center; + return c.getCableColor(); + } + return AEColor.Transparent; + } + + @Override + public IFacadeContainer getFacadeContainer() + { + return fc; + } + + @Override + public void clearContainer() + { + throw new RuntimeException( "Now thats silly!" ); + } + + @Override + public boolean isBlocked(ForgeDirection side) + { + return tcb.isBlocked( side ); + } + + public int getLightValue() + { + int light = 0; + for (ForgeDirection d : ForgeDirection.values()) + { + IPart p = getPart( d ); + if ( p != null ) + light = Math.max( p.getLightLevel(), light ); + } + return light; + } + + public boolean recolourBlock(ForgeDirection side, int colour) + { + IPart cable = getPart( ForgeDirection.UNKNOWN ); + if ( cable != null ) + { + IPartCable pc = (IPartCable) cable; + + AEColor colors[] = AEColor.values(); + if ( colors.length > colour ) + return pc.changeColor( colors[colour] ); + } + return false; + } + + public boolean activate(EntityPlayer player, Vec3 pos) + { + SelectedPart p = selectPart( pos ); + if ( p != null && p.part != null ) + { + return p.part.onActivate( player, pos ); + } + return false; + } + + @Override + public SelectedPart selectPart(Vec3 pos) + { + for (ForgeDirection side : ForgeDirection.values()) + { + IPart p = getPart( side ); + if ( p != null ) + { + List boxes = new LinkedList(); + + IPartCollsionHelper bch = new BusCollisionHelper( boxes, side ); + p.getBoxes( bch ); + for (AxisAlignedBB bb : boxes) + { + bb = bb.expand( 0.002, 0.002, 0.002 ); + if ( bb.isVecInside( pos ) ) + { + return new SelectedPart( p, side ); + } + } + } + } + + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + { + IFacadePart p = fc.getFacade( side ); + if ( p != null ) + { + List boxes = new LinkedList(); + + IPartCollsionHelper bch = new BusCollisionHelper( boxes, side ); + p.getBoxes( bch ); + for (AxisAlignedBB bb : boxes) + { + bb = bb.expand( 0.01, 0.01, 0.01 ); + if ( bb.isVecInside( pos ) ) + { + return new SelectedPart( p, side ); + } + } + } + } + + return new SelectedPart(); + } + + @Override + public void PartChanged() + { + tcb.PartChanged(); + } + + @Override + public void markForSave() + { + tcb.markForSave(); + } + + public void randomDisplayTick(World world, int x, int y, int z, Random r) + { + for (ForgeDirection side : ForgeDirection.values()) + { + IPart p = getPart( side ); + if ( p != null ) + { + p.randomDisplayTick( world, x, y, z, r ); + } + } + } + + @Override + public boolean hasRedstone(ForgeDirection side) + { + return hasRedstone; + } + +} diff --git a/parts/PartBasicState.java b/parts/PartBasicState.java new file mode 100644 index 00000000..8a25e36e --- /dev/null +++ b/parts/PartBasicState.java @@ -0,0 +1,115 @@ +package appeng.parts; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.me.GridAccessException; + +public class PartBasicState extends AEBasePart +{ + + protected final int POWERED_FLAG = 1; + protected final int CHANNEL_FLAG = 2; + + protected int clientFlags = 0; // sent as byte. + + @MENetworkEventSubscribe + public void chanRender(MENetworkChannelsChanged c) + { + getHost().markForUpdate(); + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + getHost().markForUpdate(); + } + + public void setColors(boolean hasChan, boolean hasPower) + { + if ( hasChan ) + { + int l = 14; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( getColor().blackVariant ); + } + else if ( hasPower ) + { + int l = 9; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( getColor().whiteVariant ); + } + else + { + Tessellator.instance.setBrightness( 0 ); + Tessellator.instance.setColorOpaque_I( 0x000000 ); + } + } + + public void renderLights(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + setColors( (clientFlags & (POWERED_FLAG | CHANNEL_FLAG)) == (POWERED_FLAG | CHANNEL_FLAG), (clientFlags & POWERED_FLAG) == POWERED_FLAG ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.EAST, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.WEST, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.UP, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.DOWN, renderer ); + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + super.writeToStream( data ); + + clientFlags = 0; + + try + { + if ( proxy.getEnergy().isNetworkPowered() ) + clientFlags |= POWERED_FLAG; + + if ( proxy.getNode().meetsChannelRequirements() ) + clientFlags |= CHANNEL_FLAG; + + clientFlags = populateFlags( clientFlags ); + } + catch (GridAccessException e) + { + // meh + } + + data.writeByte( (byte) clientFlags ); + } + + protected int populateFlags(int cf) + { + return cf; + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + boolean eh = super.readFromStream( data ); + + int old = clientFlags; + clientFlags = data.readByte(); + + return eh || old != clientFlags; + } + + public PartBasicState(Class c, ItemStack is) { + super( c, is ); + proxy.setFlags( GridFlags.REQURE_CHANNEL ); + } + +} diff --git a/parts/automation/PartAnnihilationPlane.java b/parts/automation/PartAnnihilationPlane.java new file mode 100644 index 00000000..e3096a8f --- /dev/null +++ b/parts/automation/PartAnnihilationPlane.java @@ -0,0 +1,127 @@ +package appeng.parts.automation; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; + +public class PartAnnihilationPlane extends PartBasicState +{ + + public PartAnnihilationPlane(ItemStack is) { + super( PartAnnihilationPlane.class, is ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 1, 1, 15, 15, 15, 16 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + int minX = 1; + int minY = 1; + int maxX = 15; + int maxY = 15; + + ForgeDirection e = rh.getWorldX(); + ForgeDirection u = rh.getWorldY(); + + TileEntity te = getHost().getTile(); + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - e.offsetX, y - e.offsetY, z - e.offsetZ ), side ) ) + minX = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + e.offsetX, y + e.offsetY, z + e.offsetZ ), side ) ) + maxX = 16; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - u.offsetX, y - u.offsetY, z - u.offsetZ ), side ) ) + minY = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + u.offsetX, y + u.offsetY, z + u.offsetZ ), side ) ) + maxY = 16; + + boolean isActive = (clientFlags & (POWERED_FLAG | CHANNEL_FLAG)) == (POWERED_FLAG | CHANNEL_FLAG); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), + CableBusTextures.PartTransitionPlaneBack.getIcon(), isActive ? CableBusTextures.BlockAnnihilationPlaneOn.getIcon() : is.getIconIndex(), + CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( minX, minY, 15, maxX, maxY, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartTransitionPlaneBack.getIcon(), isActive ? CableBusTextures.BlockAnnihilationPlaneOn.getIcon() : is.getIconIndex(), + CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + private boolean isTransitionPlane(TileEntity blockTileEntity, ForgeDirection side) + { + if ( blockTileEntity instanceof IPartHost ) + { + IPart p = ((IPartHost) blockTileEntity).getPart( side ); + return p instanceof PartAnnihilationPlane; + } + return false; + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + int minX = 1; + int minY = 1; + int maxX = 15; + int maxY = 15; + + TileEntity te = getHost().getTile(); + + int x = te.xCoord; + int y = te.yCoord; + int z = te.zCoord; + + ForgeDirection e = bch.getWorldX(); + ForgeDirection u = bch.getWorldY(); + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - e.offsetX, y - e.offsetY, z - e.offsetZ ), side ) ) + minX = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + e.offsetX, y + e.offsetY, z + e.offsetZ ), side ) ) + maxX = 16; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - u.offsetX, y - u.offsetY, z - u.offsetZ ), side ) ) + minY = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + u.offsetX, y + u.offsetY, z + u.offsetZ ), side ) ) + maxY = 16; + + bch.addBox( 5, 5, 14, 11, 11, 15 ); + bch.addBox( minX, minY, 15, maxX, maxY, 16 ); + } + + @Override + public int cableConnectionRenderTo() + { + return 1; + } + +} diff --git a/parts/automation/PartExportBus.java b/parts/automation/PartExportBus.java new file mode 100644 index 00000000..a436a0c4 --- /dev/null +++ b/parts/automation/PartExportBus.java @@ -0,0 +1,74 @@ +package appeng.parts.automation; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; + +public class PartExportBus extends PartBasicState +{ + + public PartExportBus(ItemStack is) { + super( PartExportBus.class, is ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 4, 4, 12, 12, 12, 14 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 6, 6, 15, 10, 10, 16 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 4, 4, 12, 12, 12, 14 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 6, 6, 15, 10, 10, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorBack.getIcon(), is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 6, 6, 11, 10, 10, 12 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + @Override + public int cableConnectionRenderTo() + { + return 5; + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 4, 4, 12, 12, 12, 14 ); + bch.addBox( 5, 5, 14, 11, 11, 15 ); + bch.addBox( 6, 6, 15, 10, 10, 16 ); + bch.addBox( 6, 6, 11, 10, 10, 12 ); + } + +} diff --git a/parts/automation/PartFormationPlane.java b/parts/automation/PartFormationPlane.java new file mode 100644 index 00000000..8df133dc --- /dev/null +++ b/parts/automation/PartFormationPlane.java @@ -0,0 +1,127 @@ +package appeng.parts.automation; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; + +public class PartFormationPlane extends PartBasicState +{ + + public PartFormationPlane(ItemStack is) { + super( PartFormationPlane.class, is ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 1, 1, 15, 15, 15, 16 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + int minX = 1; + int minY = 1; + int maxX = 15; + int maxY = 15; + + ForgeDirection e = rh.getWorldX(); + ForgeDirection u = rh.getWorldY(); + + TileEntity te = getHost().getTile(); + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - e.offsetX, y - e.offsetY, z - e.offsetZ ), side ) ) + minX = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + e.offsetX, y + e.offsetY, z + e.offsetZ ), side ) ) + maxX = 16; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - u.offsetX, y - u.offsetY, z - u.offsetZ ), side ) ) + minY = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + u.offsetX, y + u.offsetY, z + u.offsetZ ), side ) ) + maxY = 16; + + boolean isActive = (clientFlags & (POWERED_FLAG | CHANNEL_FLAG)) == (POWERED_FLAG | CHANNEL_FLAG); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), + CableBusTextures.PartTransitionPlaneBack.getIcon(), isActive ? CableBusTextures.BlockFormPlaneOn.getIcon() : is.getIconIndex(), + CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( minX, minY, 15, maxX, maxY, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartTransitionPlaneBack.getIcon(), isActive ? CableBusTextures.BlockFormPlaneOn.getIcon() : is.getIconIndex(), + CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 5, 5, 14, 11, 11, 15 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + private boolean isTransitionPlane(TileEntity blockTileEntity, ForgeDirection side) + { + if ( blockTileEntity instanceof IPartHost ) + { + IPart p = ((IPartHost) blockTileEntity).getPart( side ); + return p instanceof PartFormationPlane; + } + return false; + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + int minX = 1; + int minY = 1; + int maxX = 15; + int maxY = 15; + + TileEntity te = getHost().getTile(); + + int x = te.xCoord; + int y = te.yCoord; + int z = te.zCoord; + + ForgeDirection e = bch.getWorldX(); + ForgeDirection u = bch.getWorldY(); + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - e.offsetX, y - e.offsetY, z - e.offsetZ ), side ) ) + minX = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + e.offsetX, y + e.offsetY, z + e.offsetZ ), side ) ) + maxX = 16; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x - u.offsetX, y - u.offsetY, z - u.offsetZ ), side ) ) + minY = 0; + + if ( isTransitionPlane( te.worldObj.getBlockTileEntity( x + u.offsetX, y + u.offsetY, z + u.offsetZ ), side ) ) + maxY = 16; + + bch.addBox( 5, 5, 14, 11, 11, 15 ); + bch.addBox( minX, minY, 15, maxX, maxY, 16 ); + } + + @Override + public int cableConnectionRenderTo() + { + return 1; + } + +} diff --git a/parts/automation/PartImportBus.java b/parts/automation/PartImportBus.java new file mode 100644 index 00000000..368ce425 --- /dev/null +++ b/parts/automation/PartImportBus.java @@ -0,0 +1,72 @@ +package appeng.parts.automation; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; + +public class PartImportBus extends PartBasicState +{ + + public PartImportBus(ItemStack is) { + super( PartImportBus.class, is ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 3, 3, 15, 13, 13, 16 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 4, 4, 14, 12, 12, 15 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 5, 5, 13, 11, 11, 14 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 4, 4, 14, 12, 12, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 5, 5, 13, 11, 11, 14 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 6, 6, 12, 10, 10, 13 ); + rh.renderBlock( x, y, z, renderer ); + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorBack.getIcon(), is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 6, 6, 11, 10, 10, 12 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 6, 6, 11, 10, 10, 12 ); + bch.addBox( 6, 6, 12, 10, 10, 13 ); + bch.addBox( 5, 5, 13, 11, 11, 14 ); + bch.addBox( 4, 4, 14, 12, 12, 16 ); + } + + @Override + public int cableConnectionRenderTo() + { + return 5; + } + +} diff --git a/parts/automation/PartLevelEmitter.java b/parts/automation/PartLevelEmitter.java new file mode 100644 index 00000000..2ed33d5b --- /dev/null +++ b/parts/automation/PartLevelEmitter.java @@ -0,0 +1,274 @@ +package appeng.parts.automation; + +import java.util.Random; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; +import appeng.util.Platform; + +public class PartLevelEmitter extends PartBasicState +{ + + final int FLAG_ON = 4; + + @Override + protected int populateFlags(int cf) + { + return cf | (isLevelEmitterOn() ? FLAG_ON : 0); + } + + public PartLevelEmitter(ItemStack is) { + super( PartLevelEmitter.class, is ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( is.getIconIndex() ); + Tessellator.instance.startDrawingQuads(); + renderTorchAtAngle( 0, -0.5, 0 ); + Tessellator.instance.draw(); + // rh.setBounds( 7, 7, 10, 9, 9, 15 ); + // rh.renderInventoryBox( renderer ); + } + + double cenx; + double ceny; + double cenz; + + public void addVertexWithUV(double x, double y, double z, double u, double v) + { + Tessellator var12 = Tessellator.instance; + + x -= cenx; + y -= ceny; + z -= cenz; + + if ( side == ForgeDirection.DOWN ) + { + y = -y; + z = -z; + } + + if ( side == ForgeDirection.EAST ) + { + double m = x; + x = y; + y = m; + y = -y; + } + + if ( side == ForgeDirection.WEST ) + { + double m = x; + x = -y; + y = m; + } + + if ( side == ForgeDirection.SOUTH ) + { + double m = z; + z = y; + y = m; + y = -y; + } + + if ( side == ForgeDirection.NORTH ) + { + double m = z; + z = -y; + y = m; + } + + x += cenx;// + orientation.offsetX * 0.4; + y += ceny;// + orientation.offsetY * 0.4; + z += cenz;// + orientation.offsetZ * 0.4; + + var12.addVertexWithUV( x, y, z, u, v ); + } + + @Override + public void randomDisplayTick(World world, int x, int y, int z, Random r) + { + if ( isLevelEmitterOn() ) + { + ForgeDirection d = side; + + double d0 = (double) ((float) d.offsetX * 0.45F) + (double) (r.nextFloat() - 0.5F) * 0.2D; + double d1 = (double) ((float) d.offsetY * 0.45F) + (double) (r.nextFloat() - 0.5F) * 0.2D; + double d2 = (double) ((float) d.offsetZ * 0.45F) + (double) (r.nextFloat() - 0.5F) * 0.2D; + + world.spawnParticle( "reddust", 0.5 + x + d0, 0.5 + y + d1, 0.5 + z + d2, 0.0D, 0.0D, 0.0D ); + } + } + + public void renderTorchAtAngle(double baseX, double baseY, double baseZ) + { + boolean isOn = isLevelEmitterOn(); + Icon icon = (isOn ? CableBusTextures.LevelEmitterTorchOn.getIcon() : is.getIconIndex()); + // + cenx = baseX + 0.5; + ceny = baseY + 0.5; + cenz = baseZ + 0.5; + + baseY += 7.0 / 16.0; + ; + double par10 = 0; + // double par11 = 0; + double Zero = 0; + + /* + * double d5 = (double)icon.func_94209_e(); double d6 = (double)icon.func_94206_g(); double d7 = + * (double)icon.func_94212_f(); double d8 = (double)icon.func_94210_h(); double d9 = + * (double)icon.func_94214_a(7.0D); double d10 = (double)icon.func_94207_b(6.0D); double d11 = + * (double)icon.func_94214_a(9.0D); double d12 = (double)icon.func_94207_b(8.0D); double d13 = + * (double)icon.func_94214_a(7.0D); double d14 = (double)icon.func_94207_b(13.0D); double d15 = + * (double)icon.func_94214_a(9.0D); double d16 = (double)icon.func_94207_b(15.0D); + */ + + float var16 = icon.getMinU(); + float var17 = icon.getMaxU(); + float var18 = icon.getMinV(); + float var19 = icon.getMaxV(); + /* + * float var16 = (float)var14 / 256.0F; float var17 = ((float)var14 + 15.99F) / 256.0F; float var18 = + * (float)var15 / 256.0F; float var19 = ((float)var15 + 15.99F) / 256.0F; + */ + double var20 = (double) icon.getInterpolatedU( 7.0D ); + double var24 = (double) icon.getInterpolatedU( 9.0D ); + double var22 = (double) icon.getInterpolatedV( 6.0D + (isOn ? 0 : 1.0D) ); + double var26 = (double) icon.getInterpolatedV( 8.0D + (isOn ? 0 : 1.0D) ); + double var28 = (double) icon.getInterpolatedU( 7.0D ); + double var30 = (double) icon.getInterpolatedV( 13.0D ); + double var32 = (double) icon.getInterpolatedU( 9.0D ); + double var34 = (double) icon.getInterpolatedV( 15.0D ); + + double var22b = (double) icon.getInterpolatedV( 9.0D ); + double var26b = (double) icon.getInterpolatedV( 11.0D ); + + baseX += 0.5D; + baseZ += 0.5D; + double var36 = baseX - 0.5D; + double var38 = baseX + 0.5D; + double var40 = baseZ - 0.5D; + double var42 = baseZ + 0.5D; + double var44 = 0.0625D; + double var422 = 0.1915D; + double TorchLen = 0.625D; + + double toff = 0.0d; + + if ( !isOn ) + { + toff = 1.0d / 16.0d; + } + + Tessellator var12 = Tessellator.instance; + if ( isOn ) + { + var12.setColorOpaque_F( 1.0F, 1.0F, 1.0F ); + var12.setBrightness( 11 << 20 | 11 << 4 ); + } + + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) - var44, baseY + TorchLen - toff, baseZ + par10 * (1.0D - TorchLen) - var44, var20, var22 ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) - var44, baseY + TorchLen - toff, baseZ + par10 * (1.0D - TorchLen) + var44, var20, var26 ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) + var44, baseY + TorchLen - toff, baseZ + par10 * (1.0D - TorchLen) + var44, var24, var26 ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) + var44, baseY + TorchLen - toff, baseZ + par10 * (1.0D - TorchLen) - var44, var24, var22 ); + + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) + var44, baseY + var422, baseZ + par10 * (1.0D - TorchLen) - var44, var24, var22b ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) + var44, baseY + var422, baseZ + par10 * (1.0D - TorchLen) + var44, var24, var26b ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) - var44, baseY + var422, baseZ + par10 * (1.0D - TorchLen) + var44, var20, var26b ); + this.addVertexWithUV( baseX + Zero * (1.0D - TorchLen) - var44, baseY + var422, baseZ + par10 * (1.0D - TorchLen) - var44, var20, var22b ); + + this.addVertexWithUV( baseX + var44 + Zero, baseY, baseZ - var44 + par10, var32, var30 ); + this.addVertexWithUV( baseX + var44 + Zero, baseY, baseZ + var44 + par10, var32, var34 ); + this.addVertexWithUV( baseX - var44 + Zero, baseY, baseZ + var44 + par10, var28, var34 ); + this.addVertexWithUV( baseX - var44 + Zero, baseY, baseZ - var44 + par10, var28, var30 ); + + this.addVertexWithUV( baseX - var44, baseY + 1.0D, var40, (double) var16, (double) var18 ); + this.addVertexWithUV( baseX - var44 + Zero, baseY + 0.0D, var40 + par10, (double) var16, (double) var19 ); + this.addVertexWithUV( baseX - var44 + Zero, baseY + 0.0D, var42 + par10, (double) var17, (double) var19 ); + this.addVertexWithUV( baseX - var44, baseY + 1.0D, var42, (double) var17, (double) var18 ); + + this.addVertexWithUV( baseX + var44, baseY + 1.0D, var42, (double) var16, (double) var18 ); + this.addVertexWithUV( baseX + Zero + var44, baseY + 0.0D, var42 + par10, (double) var16, (double) var19 ); + this.addVertexWithUV( baseX + Zero + var44, baseY + 0.0D, var40 + par10, (double) var17, (double) var19 ); + this.addVertexWithUV( baseX + var44, baseY + 1.0D, var40, (double) var17, (double) var18 ); + + this.addVertexWithUV( var36, baseY + 1.0D, baseZ + var44, (double) var16, (double) var18 ); + this.addVertexWithUV( var36 + Zero, baseY + 0.0D, baseZ + var44 + par10, (double) var16, (double) var19 ); + this.addVertexWithUV( var38 + Zero, baseY + 0.0D, baseZ + var44 + par10, (double) var17, (double) var19 ); + this.addVertexWithUV( var38, baseY + 1.0D, baseZ + var44, (double) var17, (double) var18 ); + + this.addVertexWithUV( var38, baseY + 1.0D, baseZ - var44, (double) var16, (double) var18 ); + this.addVertexWithUV( var38 + Zero, baseY + 0.0D, baseZ - var44 + par10, (double) var16, (double) var19 ); + this.addVertexWithUV( var36 + Zero, baseY + 0.0D, baseZ - var44 + par10, (double) var17, (double) var19 ); + this.addVertexWithUV( var36, baseY + 1.0D, baseZ - var44, (double) var17, (double) var18 ); + } + + boolean status = false;; + + private boolean isLevelEmitterOn() + { + if ( Platform.isClient() ) + return (clientFlags & FLAG_ON) == FLAG_ON; + + return false; + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( is.getIconIndex() ); + // rh.setTexture( CableBusTextures.ItemPartLevelEmitterOn.getIcon() ); + + // rh.setBounds( 2, 2, 14, 14, 14, 16 ); + // rh.renderBlock( x, y, z, renderer ); + + // rh.setBounds( 7, 7, 10, 9, 9, 15 ); + // rh.renderBlock( x, y, z, renderer ); + + renderer.renderAllFaces = true; + + Tessellator tess = Tessellator.instance; + tess.setBrightness( rh.getBlock().getMixedBrightnessForBlock( this.getHost().getTile().worldObj, x, y, z ) ); + tess.setColorOpaque_F( 1.0F, 1.0F, 1.0F ); + + renderTorchAtAngle( x, y, z ); + + renderer.renderAllFaces = false; + + rh.setBounds( 7, 7, 11, 9, 9, 12 ); + renderLights( x, y, z, rh, renderer ); + + // super.renderWorldBlock( world, x, y, z, block, modelId, renderer ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 7, 7, 10, 9, 9, 16 ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public int cableConnectionRenderTo() + { + return 16; + } + +} diff --git a/parts/misc/PartCableAnchor.java b/parts/misc/PartCableAnchor.java new file mode 100644 index 00000000..dd20d411 --- /dev/null +++ b/parts/misc/PartCableAnchor.java @@ -0,0 +1,191 @@ +package appeng.parts.misc; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Random; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; + +public class PartCableAnchor implements IPart +{ + + ItemStack is = null; + + public PartCableAnchor(ItemStack is) { + this.is = is; + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + Icon myIcon = is.getIconIndex(); + rh.setTexture( myIcon ); + rh.setBounds( 7, 7, 10, 9, 9, 16 ); + rh.renderBlock( x, y, z, renderer ); + rh.setTexture( null ); + } + + @Override + public void randomDisplayTick(World world, int x, int y, int z, Random r) + { + + } + + @Override + public void renderInventory(IPartRenderHelper instance, RenderBlocks renderer) + { + instance.setTexture( is.getIconIndex() ); + instance.setBounds( 7, 7, 4, 9, 9, 14 ); + instance.renderInventoryBox( renderer ); + instance.setTexture( null ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 7, 7, 10, 9, 9, 16 ); + } + + @Override + public ItemStack getItemStack(boolean wrenched) + { + return is; + } + + @Override + public void renderDynamic(double x, double y, double z, IPartRenderHelper rh, RenderBlocks renderer) + { + + } + + @Override + public boolean isSolid() + { + return false; + } + + @Override + public boolean canConnectRedstone() + { + return false; + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + + } + + @Override + public int getLightLevel() + { + return 0; + } + + @Override + public void onNeighborChanged() + { + + } + + @Override + public int isProvidingStrongPower() + { + return 0; + } + + @Override + public int isProvidingWeakPower() + { + return 0; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + return false; + } + + @Override + public IGridNode getGridNode() + { + return null; + } + + @Override + public void onEntityCollision(Entity entity) + { + + } + + @Override + public void removeFromWorld() + { + + } + + @Override + public void addToWorld() + { + + } + + @Override + public IGridNode getExternalFacingNode() + { + return null; + } + + @Override + public void setPartHostInfo(ForgeDirection side, IPartHost host, TileEntity tile) + { + + } + + @Override + public boolean onActivate(EntityPlayer player, Vec3 pos) + { + return false; + } + + @Override + public void getDrops(List drops, boolean wrenched) + { + + } + + @Override + public int cableConnectionRenderTo() + { + return 0; + } + +} diff --git a/parts/misc/PartInvertedToggleBus.java b/parts/misc/PartInvertedToggleBus.java new file mode 100644 index 00000000..492cebb2 --- /dev/null +++ b/parts/misc/PartInvertedToggleBus.java @@ -0,0 +1,18 @@ +package appeng.parts.misc; + +import net.minecraft.item.ItemStack; + +public class PartInvertedToggleBus extends PartToggleBus +{ + + public PartInvertedToggleBus(ItemStack is) { + super( PartInvertedToggleBus.class, is ); + } + + @Override + protected boolean getIntention() + { + return !super.getIntention(); + } + +} diff --git a/parts/misc/PartP2PTunnel.java b/parts/misc/PartP2PTunnel.java new file mode 100644 index 00000000..07b97993 --- /dev/null +++ b/parts/misc/PartP2PTunnel.java @@ -0,0 +1,87 @@ +package appeng.parts.misc; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.parts.PartBasicState; + +public class PartP2PTunnel extends PartBasicState +{ + + public boolean output; + public long freq; + + public PartP2PTunnel(ItemStack is) { + super( PartP2PTunnel.class, is ); + } + + public void onChange() + { + + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( AEApi.instance().blocks().blockQuartz.block().getIcon( 0, 0 ) ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderInventoryBox( renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.BlockP2PTunnel2.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( AEApi.instance().blocks().blockQuartz.block().getIcon( 0, 0 ) ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.BlockP2PTunnel2.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 3, 3, 13, 13, 13, 14 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.BlockP2PTunnel3.getIcon() ); + + rh.setBounds( 6, 5, 12, 10, 11, 13 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 5, 6, 12, 11, 10, 13 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + @Override + public void setColors(boolean hasChan, boolean hasPower) + { + super.setColors( hasChan, hasPower ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 2, 2, 14, 14, 14, 16 ); + } + + @Override + public int cableConnectionRenderTo() + { + return 1; + } + +} diff --git a/parts/misc/PartStorageBus.java b/parts/misc/PartStorageBus.java new file mode 100644 index 00000000..5eac7dc5 --- /dev/null +++ b/parts/misc/PartStorageBus.java @@ -0,0 +1,279 @@ +package appeng.parts.misc; + +import java.util.Arrays; +import java.util.List; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.storage.ICellContainer; +import appeng.api.storage.IExternalStorageHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMontorHandlerReciever; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.client.texture.CableBusTextures; +import appeng.me.GridAccessException; +import appeng.me.storage.MEInventoryHandler; +import appeng.me.storage.MEMonitorIInventory; +import appeng.parts.PartBasicState; + +public class PartStorageBus extends PartBasicState implements IGridTickable, ICellContainer, IMEMontorHandlerReciever +{ + + int priority = 0; + + public PartStorageBus(ItemStack is) { + super( PartStorageBus.class, is ); + } + + boolean cached = false; + MEMonitorIInventory monitor = null; + MEInventoryHandler handler = null; + + int handlerHash = 0; + + @Override + public boolean isValid(Object verificationToken) + { + return handler == verificationToken; + } + + @Override + public void onNeighborChanged() + { + cached = false; + try + { + proxy.getGrid().postEvent( new MENetworkCellArrayUpdate() ); + } + catch (GridAccessException e) + { + // :3 + } + } + + private MEInventoryHandler getHandler() + { + if ( cached ) + return handler; + + boolean wasSleeping = monitor == null; + + cached = true; + TileEntity self = getHost().getTile(); + TileEntity target = self.worldObj.getBlockTileEntity( self.xCoord + side.offsetX, self.yCoord + side.offsetY, self.zCoord + side.offsetZ ); + + int newHandlerHash = generateTileHash( target ); + + if ( handlerHash == newHandlerHash ) + return handler; + + handlerHash = newHandlerHash; + handler = null; + monitor = null; + if ( target != null ) + { + IExternalStorageHandler esh = AEApi.instance().registries().externalStorage().getHandler( target, side.getOpposite(), StorageChannel.ITEMS ); + if ( esh != null ) + { + IMEInventory inv = esh.getInventory( target, side.getOpposite(), StorageChannel.ITEMS ); + + if ( inv instanceof MEMonitorIInventory ) + monitor = (MEMonitorIInventory) inv; + + if ( inv != null ) + { + handler = new MEInventoryHandler( inv ); + + if ( inv instanceof IMEMonitor ) + ((IMEMonitor) inv).addListener( this, handler ); + } + } + } + + // update sleep state... + if ( wasSleeping != (monitor == null) ) + { + try + { + ITickManager tm = proxy.getTick(); + if ( monitor == null ) + tm.sleepDevice( proxy.getNode() ); + else + tm.wakeDevice( proxy.getNode() ); + } + catch (GridAccessException e) + { + // :( + } + } + + return handler; + } + + /** + * generates a hash for a tile to detect if the tile has changed, or changed settings, if it does it will re-gen the + * handler. + */ + private int generateTileHash(TileEntity target) + { + if ( target == null ) + return 0; + + int hash = target.hashCode(); + + if ( target instanceof IInventory ) + hash ^= ((IInventory) target).getSizeInventory(); + + if ( target instanceof ISidedInventory ) + { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + int offset = 0; + for (Integer Side : ((ISidedInventory) target).getAccessibleSlotsFromSide( dir.ordinal() )) + { + hash ^= Side << (offset++ % 20); + } + } + } + + return hash; + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 3, 3, 15, 13, 13, 16 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 2, 2, 14, 14, 14, 15 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 5, 5, 12, 11, 11, 14 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 3, 3, 15, 13, 13, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 2, 2, 14, 14, 14, 15 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + is.getIconIndex(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 5, 5, 12, 11, 11, 13 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorBack.getIcon(), is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 5, 5, 13, 11, 11, 14 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 3, 3, 15, 13, 13, 16 ); + bch.addBox( 2, 2, 14, 14, 14, 15 ); + bch.addBox( 5, 5, 12, 11, 11, 13 ); + bch.addBox( 5, 5, 13, 11, 11, 14 ); + } + + @Override + public int cableConnectionRenderTo() + { + return 4; + } + + @Override + public TickingRequest getTickingRequest(IGridNode node) + { + return new TickingRequest( 5, 20 * 3, monitor == null, false ); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) + { + if ( monitor != null ) + return monitor.onTick(); + + return TickRateModulation.SLEEP; + } + + @Override + public void writeToNBT(NBTTagCompound extra) + { + super.writeToNBT( extra ); + extra.setInteger( "priority", priority ); + } + + public void readFromNBT(NBTTagCompound extra) + { + super.readFromNBT( extra ); + priority = extra.getInteger( "priority" ); + }; + + @Override + public List getCellArray(StorageChannel channel) + { + IMEInventoryHandler out = getHandler(); + if ( out == null ) + return Arrays.asList( new IMEInventoryHandler[] {} ); + return Arrays.asList( new IMEInventoryHandler[] { out } ); + } + + @Override + public int getPriority() + { + return priority; + } + + @Override + public void blinkCell(int slot) + { + } + + @Override + public void postChange(IAEItemStack change) + { + try + { + proxy.getStorage().postAlterationOfStoredItems( StorageChannel.ITEMS, change ); + } + catch (GridAccessException e) + { + // :( + } + } + +} diff --git a/parts/misc/PartToggleBus.java b/parts/misc/PartToggleBus.java new file mode 100644 index 00000000..68a8817a --- /dev/null +++ b/parts/misc/PartToggleBus.java @@ -0,0 +1,197 @@ +package appeng.parts.misc; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.AEApi; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.client.texture.CableBusTextures; +import appeng.me.helpers.AENetworkProxy; +import appeng.parts.PartBasicState; + +public class PartToggleBus extends PartBasicState +{ + + AENetworkProxy outerProxy = new AENetworkProxy( this, "outer", true ); + IGridConnection connection; + + protected final int REDSTONE_FLAG = 4; + + boolean hasRedstone = false; + + @Override + protected int populateFlags(int cf) + { + return cf | (getIntention() ? REDSTONE_FLAG : 0); + } + + @Override + public void onNeighborChanged() + { + boolean oldHasRedstone = hasRedstone; + hasRedstone = getHost().hasRedstone( side ); + + if ( hasRedstone != oldHasRedstone ) + { + updateInternalState(); + getHost().markForUpdate(); + } + } + + public PartToggleBus(ItemStack is) { + this( PartToggleBus.class, is ); + } + + public PartToggleBus(Class cls, ItemStack is) { + super( cls, is ); + } + + @Override + public void setPartHostInfo(ForgeDirection side, IPartHost host, TileEntity tile) + { + super.setPartHostInfo( side, host, tile ); + outerProxy.setValidSides( EnumSet.of( side ) ); + } + + @Override + public void readFromNBT(NBTTagCompound extra) + { + super.readFromNBT( extra ); + outerProxy.readFromNBT( extra ); + } + + @Override + public void writeToNBT(NBTTagCompound extra) + { + super.writeToNBT( extra ); + outerProxy.writeToNBT( extra ); + } + + @Override + public void addToWorld() + { + super.addToWorld(); + outerProxy.onReady(); + updateInternalState(); + } + + private void updateInternalState() + { + boolean intention = getIntention(); + if ( intention != (connection != null) ) + { + if ( proxy.getNode() != null && outerProxy.getNode() != null ) + { + if ( intention ) + { + connection = AEApi.instance().createGridConnection( proxy.getNode(), outerProxy.getNode() ); + } + else + { + connection.destroy(); + connection = null; + } + } + } + } + + protected boolean getIntention() + { + return getHost().hasRedstone( side ); + } + + @Override + public void removeFromWorld() + { + super.removeFromWorld(); + outerProxy.invalidate(); + } + + @Override + public IGridNode getExternalFacingNode() + { + return outerProxy.getNode(); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.GLASS; + } + + @Override + public void setColors(boolean hasChan, boolean hasPower) + { + hasRedstone = (clientFlags & REDSTONE_FLAG) == REDSTONE_FLAG; + super.setColors( hasChan && hasRedstone, hasPower && hasRedstone ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( is.getIconIndex() ); + + rh.setBounds( 6, 6, 14, 10, 10, 16 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setBounds( 6, 6, 11, 10, 10, 13 ); + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorBack.getIcon(), is.getIconIndex(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorSidesStatus.getIcon() ); + + rh.setBounds( 6, 6, 13, 10, 10, 14 ); + rh.renderBlock( x, y, z, renderer ); + + renderLights( x, y, z, rh, renderer ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 6, 6, 11, 10, 10, 16 ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + GL11.glTranslated( -0.2, -0.3, 0.0 ); + + rh.setTexture( is.getIconIndex() ); + rh.setBounds( 6, 6, 14 - 4, 10, 10, 16 - 4 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 6, 6, 11 - 4, 10, 10, 13 - 4 ); + rh.renderInventoryBox( renderer ); + + rh.setBounds( 6, 6, 13 - 4, 10, 10, 14 - 4 ); + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon() ); + rh.renderInventoryBox( renderer ); + + rh.setTexture( CableBusTextures.PartMonitorSidesStatusLights.getIcon() ); + rh.setInvColor( 0x000000 ); + rh.renderInventoryBox( renderer ); + rh.setInvColor( 0xffffff ); + + rh.setTexture( null ); + } + + @Override + public int cableConnectionRenderTo() + { + return 5; + } +} diff --git a/parts/networking/PartCable.java b/parts/networking/PartCable.java new file mode 100644 index 00000000..00fb61ac --- /dev/null +++ b/parts/networking/PartCable.java @@ -0,0 +1,823 @@ +package appeng.parts.networking; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.AEApi; +import appeng.api.implementations.IPartCable; +import appeng.api.networking.IGridConnection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.api.util.IReadOnlyCollection; +import appeng.block.AEBaseBlock; +import appeng.client.texture.CableBusTextures; +import appeng.client.texture.FlipableIcon; +import appeng.client.texture.TaughtIcon; +import appeng.me.GridAccessException; +import appeng.me.helpers.AENetworkProxy; +import appeng.parts.AEBasePart; +import appeng.util.Platform; + +public class PartCable extends AEBasePart implements IPartCable +{ + + int channelsOnSide[] = new int[] { 0, 0, 0, 0, 0, 0 }; + + EnumSet connections = EnumSet.noneOf( ForgeDirection.class ); + boolean powered = false; + + public PartCable(Class c, ItemStack is) { + super( c, is ); + proxy.setIdlePowerUsage( 1.0 / 16.0 ); + proxy.myColor = AEColor.fromCable( is ); + } + + public Icon getGlassTexture(AEColor c) + { + switch (c) + { + case Black: + return CableBusTextures.MECable_Black.getIcon(); + case Blue: + return CableBusTextures.MECable_Blue.getIcon(); + case Brown: + return CableBusTextures.MECable_Brown.getIcon(); + case Cyan: + return CableBusTextures.MECable_Cyan.getIcon(); + case Gray: + return CableBusTextures.MECable_Grey.getIcon(); + case Green: + return CableBusTextures.MECable_Green.getIcon(); + case LightBlue: + return CableBusTextures.MECable_LightBlue.getIcon(); + case LightGray: + return CableBusTextures.MECable_LightGrey.getIcon(); + case Lime: + return CableBusTextures.MECable_Lime.getIcon(); + case Magenta: + return CableBusTextures.MECable_Magenta.getIcon(); + case Orange: + return CableBusTextures.MECable_Orange.getIcon(); + case Pink: + return CableBusTextures.MECable_Pink.getIcon(); + case Purple: + return CableBusTextures.MECable_Purple.getIcon(); + case Red: + return CableBusTextures.MECable_Red.getIcon(); + case White: + return CableBusTextures.MECable_White.getIcon(); + case Yellow: + return CableBusTextures.MECable_Yellow.getIcon(); + default: + } + return is.getIconIndex(); + } + + public Icon getTexture(AEColor c) + { + return getGlassTexture( c ); + } + + public Icon getCoveredTexture(AEColor c) + { + switch (c) + { + case Black: + return CableBusTextures.MECovered_Black.getIcon(); + case Blue: + return CableBusTextures.MECovered_Blue.getIcon(); + case Brown: + return CableBusTextures.MECovered_Brown.getIcon(); + case Cyan: + return CableBusTextures.MECovered_Cyan.getIcon(); + case Gray: + return CableBusTextures.MECovered_Gray.getIcon(); + case Green: + return CableBusTextures.MECovered_Green.getIcon(); + case LightBlue: + return CableBusTextures.MECovered_LightBlue.getIcon(); + case LightGray: + return CableBusTextures.MECovered_LightGrey.getIcon(); + case Lime: + return CableBusTextures.MECovered_Lime.getIcon(); + case Magenta: + return CableBusTextures.MECovered_Magenta.getIcon(); + case Orange: + return CableBusTextures.MECovered_Orange.getIcon(); + case Pink: + return CableBusTextures.MECovered_Pink.getIcon(); + case Purple: + return CableBusTextures.MECovered_Purple.getIcon(); + case Red: + return CableBusTextures.MECovered_Red.getIcon(); + case White: + return CableBusTextures.MECovered_White.getIcon(); + case Yellow: + return CableBusTextures.MECovered_Yellow.getIcon(); + default: + } + return AEApi.instance().parts().partCableCovered.item().getIconIndex( AEApi.instance().parts().partCableCovered.stack( 1 ) ); + } + + public Icon getSmartTexture(AEColor c) + { + switch (c) + { + case Black: + return CableBusTextures.MESmart_Black.getIcon(); + case Blue: + return CableBusTextures.MESmart_Blue.getIcon(); + case Brown: + return CableBusTextures.MESmart_Brown.getIcon(); + case Cyan: + return CableBusTextures.MESmart_Cyan.getIcon(); + case Gray: + return CableBusTextures.MESmart_Gray.getIcon(); + case Green: + return CableBusTextures.MESmart_Green.getIcon(); + case LightBlue: + return CableBusTextures.MESmart_LightBlue.getIcon(); + case LightGray: + return CableBusTextures.MESmart_LightGrey.getIcon(); + case Lime: + return CableBusTextures.MESmart_Lime.getIcon(); + case Magenta: + return CableBusTextures.MESmart_Magenta.getIcon(); + case Orange: + return CableBusTextures.MESmart_Orange.getIcon(); + case Pink: + return CableBusTextures.MESmart_Pink.getIcon(); + case Purple: + return CableBusTextures.MESmart_Purple.getIcon(); + case Red: + return CableBusTextures.MESmart_Red.getIcon(); + case White: + return CableBusTextures.MESmart_White.getIcon(); + case Yellow: + return CableBusTextures.MESmart_Yellow.getIcon(); + default: + } + + return is.getIconIndex(); + } + + @Override + public AEColor getCableColor() + { + return proxy.myColor; + } + + @Override + public AECableType getCableConnectionType() + { + return AECableType.GLASS; + } + + public AENetworkProxy getProxy() + { + return proxy; + } + + public void markForUpdate() + { + getHost().markForUpdate(); + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + int cs = 0; + int sideOut = 0; + + IGridNode n = getGridNode(); + if ( n != null ) + { + for (ForgeDirection thisSide : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getHost().getPart( thisSide ); + if ( part != null ) + { + if ( part.getGridNode() != null ) + { + IReadOnlyCollection set = part.getGridNode().getConnections(); + for (IGridConnection gc : set) + { + sideOut |= gc.getUsedChannels() << (4 * thisSide.ordinal()); + } + } + } + } + + for (IGridConnection gc : n.getConnections()) + { + ForgeDirection side = gc.getDirection( n ); + if ( side != ForgeDirection.UNKNOWN ) + { + sideOut |= gc.getUsedChannels() << (4 * side.ordinal()); + cs |= (1 << side.ordinal()); + } + } + } + + try + { + if ( proxy.getEnergy().isNetworkPowered() ) + cs |= (1 << ForgeDirection.UNKNOWN.ordinal()); + } + catch (GridAccessException e) + { + // aww... + } + + data.writeByte( (byte) cs ); + data.writeInt( sideOut ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + int cs = data.readByte(); + int sideOut = data.readInt(); + + EnumSet myC = connections; + boolean wasPowered = powered; + powered = false; + boolean chchanged = false; + + for (ForgeDirection d : ForgeDirection.values()) + { + if ( d != ForgeDirection.UNKNOWN ) + { + int ch = (sideOut >> (d.ordinal() * 4)) & 0xF; + if ( ch != channelsOnSide[d.ordinal()] ) + { + chchanged = true; + channelsOnSide[d.ordinal()] = ch; + } + } + + if ( d == ForgeDirection.UNKNOWN ) + { + int id = 1 << d.ordinal(); + if ( id == (cs & id) ) + powered = true; + } + else + { + int id = 1 << d.ordinal(); + if ( id == (cs & id) ) + connections.add( d ); + else + connections.remove( d ); + } + } + + return !myC.equals( connections ) || wasPowered != powered || chchanged; + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 6.0, 6.0, 6.0, 10.0, 10.0, 10.0 ); + + if ( Platform.isServer() ) + { + IGridNode n = getGridNode(); + if ( n != null ) + connections = n.getConnectedSides(); + else + connections.clear(); + } + + for (ForgeDirection of : connections) + { + switch (of) + { + case DOWN: + bch.addBox( 6.0, 0.0, 6.0, 10.0, 6.0, 10.0 ); + break; + case EAST: + bch.addBox( 10.0, 6.0, 6.0, 16.0, 10.0, 10.0 ); + break; + case NORTH: + bch.addBox( 6.0, 6.0, 0.0, 10.0, 10.0, 6.0 ); + break; + case SOUTH: + bch.addBox( 6.0, 6.0, 10.0, 10.0, 10.0, 16.0 ); + break; + case UP: + bch.addBox( 6.0, 10.0, 6.0, 10.0, 16.0, 10.0 ); + break; + case WEST: + bch.addBox( 0.0, 6.0, 6.0, 6.0, 10.0, 10.0 ); + break; + default: + continue; + } + } + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + GL11.glTranslated( -0.2, -0.3, 0.0 ); + + rh.setTexture( getTexture( getCableColor() ) ); + rh.setBounds( 6.0f, 6.0f, 2.0f, 10.0f, 10.0f, 14.0f ); + rh.renderInventoryBox( renderer ); + rh.setTexture( null ); + } + + public void rendereGlassConection(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer, ForgeDirection of) + { + TileEntity te = this.tile.worldObj.getBlockTileEntity( x + of.offsetX, y + of.offsetY, z + of.offsetZ ); + IPartHost ccph = te instanceof IPartHost ? (IPartHost) te : null; + IGridHost gh = te instanceof IGridHost ? (IGridHost) te : null; + + if ( gh != null && ccph != null && gh.getCableConnectionType( of ) == AECableType.GLASS && ccph.getColor() != AEColor.Transparent + && ccph.getPart( of.getOpposite() ) == null ) + rh.setTexture( getTexture( ccph.getColor() ) ); + else if ( ccph == null && gh != null && gh.getCableConnectionType( of ) != AECableType.GLASS ) + { + rh.setTexture( getCoveredTexture( getCableColor() ) ); + switch (of) + { + case DOWN: + rh.setBounds( 5, 0, 5, 11, 4, 11 ); + break; + case EAST: + rh.setBounds( 12, 5, 5, 16, 11, 11 ); + break; + case NORTH: + rh.setBounds( 5, 5, 0, 11, 11, 4 ); + break; + case SOUTH: + rh.setBounds( 5, 5, 12, 11, 11, 16 ); + break; + case UP: + rh.setBounds( 5, 12, 5, 11, 16, 11 ); + break; + case WEST: + rh.setBounds( 0, 5, 5, 4, 11, 11 ); + break; + default: + return; + } + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( getTexture( getCableColor() ) ); + } + else + rh.setTexture( getTexture( getCableColor() ) ); + + switch (of) + { + case DOWN: + rh.setBounds( 6, 0, 6, 10, 6, 10 ); + break; + case EAST: + rh.setBounds( 10, 6, 6, 16, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, 0, 10, 10, 6 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 10, 10, 10, 16 ); + break; + case UP: + rh.setBounds( 6, 10, 6, 10, 16, 10 ); + break; + case WEST: + rh.setBounds( 0, 6, 6, 6, 10, 10 ); + break; + default: + return; + } + rh.renderBlock( x, y, z, renderer ); + } + + protected CableBusTextures getChannelTex(int i, boolean b) + { + if ( !powered ) + i = 0; + + if ( b ) + { + switch (i) + { + default: + return CableBusTextures.Channels10; + case 5: + return CableBusTextures.Channels11; + case 6: + return CableBusTextures.Channels12; + case 7: + return CableBusTextures.Channels13; + case 8: + return CableBusTextures.Channels14; + } + } + else + { + switch (i) + { + case 0: + return CableBusTextures.Channels00; + case 1: + return CableBusTextures.Channels01; + case 2: + return CableBusTextures.Channels02; + case 3: + return CableBusTextures.Channels03; + default: + return CableBusTextures.Channels04; + } + } + } + + public void renderCoveredConection(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer, int channels, ForgeDirection of) + { + TileEntity te = this.tile.worldObj.getBlockTileEntity( x + of.offsetX, y + of.offsetY, z + of.offsetZ ); + IPartHost ccph = te instanceof IPartHost ? (IPartHost) te : null; + IGridHost ghh = te instanceof IGridHost ? (IGridHost) te : null; + boolean isSmart = false; + + if ( ghh != null && ccph != null && ghh.getCableConnectionType( of ) == AECableType.GLASS && ccph.getPart( of.getOpposite() ) == null ) + rh.setTexture( getGlassTexture( ccph.getColor() ) ); + else if ( ccph == null && ghh != null && ghh.getCableConnectionType( of ) != AECableType.GLASS ) + { + rh.setTexture( getCoveredTexture( getCableColor() ) ); + switch (of) + { + case DOWN: + rh.setBounds( 5, 0, 5, 11, 4, 11 ); + break; + case EAST: + rh.setBounds( 12, 5, 5, 16, 11, 11 ); + break; + case NORTH: + rh.setBounds( 5, 5, 0, 11, 11, 4 ); + break; + case SOUTH: + rh.setBounds( 5, 5, 12, 11, 11, 16 ); + break; + case UP: + rh.setBounds( 5, 12, 5, 11, 16, 11 ); + break; + case WEST: + rh.setBounds( 0, 5, 5, 4, 11, 11 ); + break; + default: + return; + } + rh.renderBlock( x, y, z, renderer ); + + rh.setTexture( getTexture( getCableColor() ) ); + } + else if ( ghh != null && ccph != null && ghh.getCableConnectionType( of ) == AECableType.COVERED && ccph.getColor() != AEColor.Transparent ) + rh.setTexture( getCoveredTexture( ccph.getColor() ) ); + else if ( ghh != null && ccph != null && ghh.getCableConnectionType( of ) == AECableType.SMART ) + { + isSmart = true; + rh.setTexture( getSmartTexture( getCableColor() ) ); + } + else + rh.setTexture( getCoveredTexture( getCableColor() ) ); + + switch (of) + { + case DOWN: + rh.setBounds( 6, 0, 6, 10, 5, 10 ); + break; + case EAST: + rh.setBounds( 11, 6, 6, 16, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, 0, 10, 10, 5 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 11, 10, 10, 16 ); + break; + case UP: + rh.setBounds( 6, 11, 6, 10, 16, 10 ); + break; + case WEST: + rh.setBounds( 0, 6, 6, 5, 10, 10 ); + break; + default: + return; + } + + rh.renderBlock( x, y, z, renderer ); + + if ( isSmart ) + { + setSmartConnectionRotations( of, renderer ); + Icon defa = new TaughtIcon( getChannelTex( channels, false ).getIcon(), -0.2f ); + Icon defb = new TaughtIcon( getChannelTex( channels, true ).getIcon(), -0.2f ); + + if ( of == ForgeDirection.EAST || of == ForgeDirection.WEST ) + { + AEBaseBlock blk = (AEBaseBlock) rh.getBlock(); + FlipableIcon ico = blk.getRendererInstance().getTexture( ForgeDirection.EAST ); + ico.setFlip( false, true ); + } + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + Tessellator.instance.setColorOpaque_I( getCableColor().mediumVariant ); + rh.setTexture( defa, defa, defa, defa, defa, defa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( getCableColor().whiteVariant ); + rh.setTexture( defb, defb, defb, defb, defb, defb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + } + } + + public void renderSmartConection(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer, int channels, ForgeDirection of) + { + TileEntity te = this.tile.worldObj.getBlockTileEntity( x + of.offsetX, y + of.offsetY, z + of.offsetZ ); + IPartHost ccph = te instanceof IPartHost ? (IPartHost) te : null; + IGridHost ghh = te instanceof IGridHost ? (IGridHost) te : null; + boolean isGlass = false; + AEColor myColor = getCableColor(); + + if ( ghh != null && ccph != null && ghh.getCableConnectionType( of ) == AECableType.GLASS && ccph.getPart( of.getOpposite() ) == null ) + { + isGlass = true; + rh.setTexture( getGlassTexture( myColor = ccph.getColor() ) ); + } + else if ( ccph == null && ghh != null && ghh.getCableConnectionType( of ) != AECableType.GLASS ) + { + rh.setTexture( getSmartTexture( myColor ) ); + switch (of) + { + case DOWN: + rh.setBounds( 5, 0, 5, 11, 4, 11 ); + break; + case EAST: + rh.setBounds( 12, 5, 5, 16, 11, 11 ); + break; + case NORTH: + rh.setBounds( 5, 5, 0, 11, 11, 4 ); + break; + case SOUTH: + rh.setBounds( 5, 5, 12, 11, 11, 16 ); + break; + case UP: + rh.setBounds( 5, 12, 5, 11, 16, 11 ); + break; + case WEST: + rh.setBounds( 0, 5, 5, 4, 11, 11 ); + break; + default: + return; + } + rh.renderBlock( x, y, z, renderer ); + + if ( true ) + { + setSmartConnectionRotations( of, renderer ); + Icon defa = new TaughtIcon( getChannelTex( channels, false ).getIcon(), -0.2f ); + Icon defb = new TaughtIcon( getChannelTex( channels, true ).getIcon(), -0.2f ); + + if ( of == ForgeDirection.EAST || of == ForgeDirection.WEST ) + { + AEBaseBlock blk = (AEBaseBlock) rh.getBlock(); + FlipableIcon ico = blk.getRendererInstance().getTexture( ForgeDirection.EAST ); + ico.setFlip( false, true ); + } + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + Tessellator.instance.setColorOpaque_I( myColor.mediumVariant ); + rh.setTexture( defa, defa, defa, defa, defa, defa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( myColor.whiteVariant ); + rh.setTexture( defb, defb, defb, defb, defb, defb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + } + + rh.setTexture( getTexture( getCableColor() ) ); + } + + else if ( ghh != null && ccph != null && ghh.getCableConnectionType( of ) != AECableType.GLASS && ccph.getColor() != AEColor.Transparent ) + rh.setTexture( getSmartTexture( myColor = ccph.getColor() ) ); + else + rh.setTexture( getSmartTexture( getCableColor() ) ); + + switch (of) + { + case DOWN: + rh.setBounds( 6, 0, 6, 10, 5, 10 ); + break; + case EAST: + rh.setBounds( 11, 6, 6, 16, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, 0, 10, 10, 5 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 11, 10, 10, 16 ); + break; + case UP: + rh.setBounds( 6, 11, 6, 10, 16, 10 ); + break; + case WEST: + rh.setBounds( 0, 6, 6, 5, 10, 10 ); + break; + default: + return; + } + + rh.renderBlock( x, y, z, renderer ); + + if ( !isGlass ) + { + setSmartConnectionRotations( of, renderer ); + + Icon defa = new TaughtIcon( getChannelTex( channels, false ).getIcon(), -0.2f ); + Icon defb = new TaughtIcon( getChannelTex( channels, true ).getIcon(), -0.2f ); + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + Tessellator.instance.setColorOpaque_I( myColor.mediumVariant ); + rh.setTexture( defa, defa, defa, defa, defa, defa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( myColor.whiteVariant ); + rh.setTexture( defb, defb, defb, defb, defb, defb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + } + } + + protected void setSmartConnectionRotations(ForgeDirection of, RenderBlocks renderer) + { + switch (of) + { + case UP: + case DOWN: + renderer.uvRotateTop = 0; + renderer.uvRotateBottom = 0; + renderer.uvRotateSouth = 3; + renderer.uvRotateEast = 3; + break; + case NORTH: + case SOUTH: + renderer.uvRotateTop = 3; + renderer.uvRotateBottom = 3; + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 2; + renderer.uvRotateWest = 1; + break; + case EAST: + case WEST: + renderer.uvRotateEast = 2; + renderer.uvRotateWest = 1; + renderer.uvRotateBottom = 2; + renderer.uvRotateTop = 1; + renderer.uvRotateSouth = 3; + renderer.uvRotateNorth = 0; + break; + default: + break; + + } + } + + protected void renderAllFaces(AEBaseBlock blk, int x, int y, int z, RenderBlocks renderer) + { + renderer.renderFaceXNeg( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.WEST ) ); + renderer.renderFaceXPos( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.EAST ) ); + renderer.renderFaceZNeg( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.NORTH ) ); + renderer.renderFaceZPos( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.SOUTH ) ); + renderer.renderFaceYNeg( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.DOWN ) ); + renderer.renderFaceYPos( blk, x, y, z, blk.getRendererInstance().getTexture( ForgeDirection.UP ) ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + boolean useCovered = false; + + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart p = getHost().getPart( dir ); + if ( p != null && p instanceof IGridHost ) + { + IGridHost igh = (IGridHost) p; + AECableType type = igh.getCableConnectionType( dir.getOpposite() ); + if ( type == AECableType.COVERED || type == AECableType.SMART ) + { + useCovered = true; + break; + } + } + } + + if ( useCovered ) + { + rh.setTexture( getCoveredTexture( getCableColor() ) ); + rh.setBounds( 5, 5, 5, 11, 11, 11 ); + rh.renderBlock( x, y, z, renderer ); + } + else + { + rh.setTexture( getTexture( getCableColor() ) ); + rh.setBounds( 6, 6, 6, 10, 10, 10 ); + rh.renderBlock( x, y, z, renderer ); + } + + IPartHost ph = getHost(); + for (ForgeDirection of : EnumSet.complementOf( connections )) + { + IPart bp = ph.getPart( of ); + if ( bp instanceof IGridHost ) + { + int len = bp.cableConnectionRenderTo(); + if ( len < 8 ) + { + switch (of) + { + case DOWN: + rh.setBounds( 6, len, 6, 10, 6, 10 ); + break; + case EAST: + rh.setBounds( 10, 6, 6, 16 - len, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, len, 10, 10, 6 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 10, 10, 10, 16 - len ); + break; + case UP: + rh.setBounds( 6, 10, 6, 10, 16 - len, 10 ); + break; + case WEST: + rh.setBounds( len, 6, 6, 6, 10, 10 ); + break; + default: + continue; + } + rh.renderBlock( x, y, z, renderer ); + } + } + } + + for (ForgeDirection of : connections) + { + rendereGlassConection( x, y, z, rh, renderer, of ); + } + + rh.setTexture( null ); + } + + @Override + public boolean changeColor(AEColor newColor) + { + if ( getCableColor() != newColor ) + { + is.setItemDamage( newColor.ordinal() ); + markForUpdate(); + return true; + } + return false; + } + + @Override + public void setValidSides(EnumSet sides) + { + proxy.setValidSides( sides ); + } + + protected boolean nonLinear(EnumSet sides) + { + return (sides.contains( ForgeDirection.EAST ) && sides.contains( ForgeDirection.WEST )) + || (sides.contains( ForgeDirection.NORTH ) && sides.contains( ForgeDirection.SOUTH )) + || (sides.contains( ForgeDirection.UP ) && sides.contains( ForgeDirection.DOWN )); + } + +} diff --git a/parts/networking/PartCableCovered.java b/parts/networking/PartCableCovered.java new file mode 100644 index 00000000..d58104eb --- /dev/null +++ b/parts/networking/PartCableCovered.java @@ -0,0 +1,210 @@ +package appeng.parts.networking; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.client.texture.OffsetIcon; +import appeng.util.Platform; + +public class PartCableCovered extends PartCable +{ + + @MENetworkEventSubscribe + public void channelUpdated(MENetworkChannelsChanged c) + { + getHost().markForUpdate(); + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + getHost().markForUpdate(); + } + + public PartCableCovered(ItemStack is) { + super( PartCableCovered.class, is ); + } + + @Override + public Icon getTexture(AEColor c) + { + return getCoveredTexture( c ); + } + + @Override + public AECableType getCableConnectionType() + { + return AECableType.COVERED; + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 5.0, 5.0, 5.0, 11.0, 11.0, 11.0 ); + + if ( Platform.isServer() ) + { + IGridNode n = getGridNode(); + if ( n != null ) + connections = n.getConnectedSides(); + else + connections.clear(); + } + + for (ForgeDirection of : connections) + { + switch (of) + { + case DOWN: + bch.addBox( 5.0, 0.0, 5.0, 11.0, 5.0, 11.0 ); + break; + case EAST: + bch.addBox( 11.0, 5.0, 5.0, 16.0, 11.0, 11.0 ); + break; + case NORTH: + bch.addBox( 5.0, 5.0, 0.0, 11.0, 11.0, 5.0 ); + break; + case SOUTH: + bch.addBox( 5.0, 5.0, 11.0, 11.0, 11.0, 16.0 ); + break; + case UP: + bch.addBox( 5.0, 11.0, 5.0, 11.0, 16.0, 11.0 ); + break; + case WEST: + bch.addBox( 0.0, 5.0, 5.0, 5.0, 11.0, 11.0 ); + break; + default: + continue; + } + } + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + GL11.glTranslated( -0.2, -0.3, 0.0 ); + + rh.setTexture( getTexture( getCableColor() ) ); + rh.setBounds( 5.0f, 5.0f, 2.0f, 11.0f, 11.0f, 14.0f ); + rh.renderInventoryBox( renderer ); + rh.setTexture( null ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( getTexture( getCableColor() ) ); + + EnumSet sides = connections.clone(); + + boolean hasBuses = false; + IPartHost ph = getHost(); + for (ForgeDirection of : EnumSet.complementOf( connections )) + { + IPart bp = ph.getPart( of ); + if ( bp instanceof IGridHost ) + { + if ( of != ForgeDirection.UNKNOWN ) + { + sides.add( of ); + hasBuses = true; + } + + int len = bp.cableConnectionRenderTo(); + if ( len < 8 ) + { + switch (of) + { + case DOWN: + rh.setBounds( 6, len, 6, 10, 5, 10 ); + break; + case EAST: + rh.setBounds( 11, 6, 6, 16 - len, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, len, 10, 10, 5 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 11, 10, 10, 16 - len ); + break; + case UP: + rh.setBounds( 6, 11, 6, 10, 16 - len, 10 ); + break; + case WEST: + rh.setBounds( len, 6, 6, 5, 10, 10 ); + break; + default: + continue; + } + rh.renderBlock( x, y, z, renderer ); + } + } + } + + if ( sides.size() != 2 || !nonLinear( sides ) || hasBuses ) + { + for (ForgeDirection of : connections) + { + renderCoveredConection( x, y, z, rh, renderer, channelsOnSide[of.ordinal()], of ); + } + + rh.setTexture( getTexture( getCableColor() ) ); + rh.setBounds( 5, 5, 5, 11, 11, 11 ); + rh.renderBlock( x, y, z, renderer ); + } + else + { + Icon def = getTexture( getCableColor() ); + Icon off = new OffsetIcon( def, 0, -12 ); + for (ForgeDirection of : connections) + { + switch (of) + { + case DOWN: + case UP: + rh.setTexture( def, def, off, off, off, off ); + renderer.setRenderBounds( 5 / 16.0, 0, 5 / 16.0, 11 / 16.0, 16 / 16.0, 11 / 16.0 ); + break; + case EAST: + case WEST: + rh.setTexture( off, off, off, off, def, def ); + renderer.uvRotateEast = renderer.uvRotateWest = 1; + renderer.uvRotateBottom = renderer.uvRotateTop = 1; + renderer.setRenderBounds( 0, 5 / 16.0, 5 / 16.0, 16 / 16.0, 11 / 16.0, 11 / 16.0 ); + break; + case NORTH: + case SOUTH: + rh.setTexture( off, off, def, def, off, off ); + renderer.uvRotateNorth = renderer.uvRotateSouth = 1; + renderer.setRenderBounds( 5 / 16.0, 5 / 16.0, 0, 11 / 16.0, 11 / 16.0, 16 / 16.0 ); + break; + default: + continue; + } + } + + renderer.renderStandardBlock( rh.getBlock(), x, y, z ); + } + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + rh.setTexture( null ); + } + +} diff --git a/parts/networking/PartCableGlass.java b/parts/networking/PartCableGlass.java new file mode 100644 index 00000000..d82dfb21 --- /dev/null +++ b/parts/networking/PartCableGlass.java @@ -0,0 +1,12 @@ +package appeng.parts.networking; + +import net.minecraft.item.ItemStack; + +public class PartCableGlass extends PartCable +{ + + public PartCableGlass(ItemStack is) { + super( PartCableGlass.class, is ); + } + +} diff --git a/parts/networking/PartCableSmart.java b/parts/networking/PartCableSmart.java new file mode 100644 index 00000000..eff9857a --- /dev/null +++ b/parts/networking/PartCableSmart.java @@ -0,0 +1,307 @@ +package appeng.parts.networking; + +import java.util.EnumSet; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.block.AEBaseBlock; +import appeng.client.texture.FlipableIcon; +import appeng.client.texture.OffsetIcon; +import appeng.client.texture.TaughtIcon; +import appeng.util.Platform; + +public class PartCableSmart extends PartCable +{ + + @MENetworkEventSubscribe + public void channelUpdated(MENetworkChannelsChanged c) + { + getHost().markForUpdate(); + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + getHost().markForUpdate(); + } + + public PartCableSmart(ItemStack is) { + super( PartCableSmart.class, is ); + } + + @Override + public AECableType getCableConnectionType() + { + return AECableType.SMART; + } + + @Override + public Icon getTexture(AEColor c) + { + return getSmartTexture( c ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + GL11.glTranslated( -0.2, -0.3, 0.0 ); + + rh.setTexture( getTexture( getCableColor() ) ); + rh.setBounds( 5.0f, 5.0f, 2.0f, 11.0f, 11.0f, 14.0f ); + rh.renderInventoryBox( renderer ); + + rh.setTexture( getChannelTex( 4, false ).getIcon() ); + rh.setBounds( 5.0f, 5.0f, 2.0f, 11.0f, 11.0f, 14.0f ); + rh.renderInventoryBox( renderer ); + + rh.setTexture( getChannelTex( 4, true ).getIcon() ); + rh.setBounds( 5.0f, 5.0f, 2.0f, 11.0f, 11.0f, 14.0f ); + rh.renderInventoryBox( renderer ); + + rh.setTexture( null ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 5.0, 5.0, 5.0, 11.0, 11.0, 11.0 ); + + if ( Platform.isServer() ) + { + IGridNode n = getGridNode(); + if ( n != null ) + connections = n.getConnectedSides(); + else + connections.clear(); + } + + for (ForgeDirection of : connections) + { + switch (of) + { + case DOWN: + bch.addBox( 5.0, 0.0, 5.0, 11.0, 5.0, 11.0 ); + break; + case EAST: + bch.addBox( 11.0, 5.0, 5.0, 16.0, 11.0, 11.0 ); + break; + case NORTH: + bch.addBox( 5.0, 5.0, 0.0, 11.0, 11.0, 5.0 ); + break; + case SOUTH: + bch.addBox( 5.0, 5.0, 11.0, 11.0, 11.0, 16.0 ); + break; + case UP: + bch.addBox( 5.0, 11.0, 5.0, 11.0, 16.0, 11.0 ); + break; + case WEST: + bch.addBox( 0.0, 5.0, 5.0, 5.0, 11.0, 11.0 ); + break; + default: + continue; + } + } + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( getTexture( getCableColor() ) ); + + EnumSet sides = connections.clone(); + + boolean hasBuses = false; + IPartHost ph = getHost(); + for (ForgeDirection of : EnumSet.complementOf( connections )) + { + IPart bp = ph.getPart( of ); + if ( bp instanceof IGridHost ) + { + if ( of != ForgeDirection.UNKNOWN ) + { + sides.add( of ); + hasBuses = true; + } + + int len = bp.cableConnectionRenderTo(); + if ( len < 8 ) + { + switch (of) + { + case DOWN: + rh.setBounds( 6, len, 6, 10, 5, 10 ); + break; + case EAST: + rh.setBounds( 11, 6, 6, 16 - len, 10, 10 ); + break; + case NORTH: + rh.setBounds( 6, 6, len, 10, 10, 5 ); + break; + case SOUTH: + rh.setBounds( 6, 6, 11, 10, 10, 16 - len ); + break; + case UP: + rh.setBounds( 6, 11, 6, 10, 16 - len, 10 ); + break; + case WEST: + rh.setBounds( len, 6, 6, 5, 10, 10 ); + break; + default: + continue; + } + rh.renderBlock( x, y, z, renderer ); + + setSmartConnectionRotations( of, renderer ); + Icon defa = new TaughtIcon( getChannelTex( channelsOnSide[of.ordinal()], false ).getIcon(), -0.2f ); + Icon defb = new TaughtIcon( getChannelTex( channelsOnSide[of.ordinal()], true ).getIcon(), -0.2f ); + + if ( of == ForgeDirection.EAST || of == ForgeDirection.WEST ) + { + AEBaseBlock blk = (AEBaseBlock) rh.getBlock(); + FlipableIcon ico = blk.getRendererInstance().getTexture( ForgeDirection.EAST ); + ico.setFlip( false, true ); + } + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + Tessellator.instance.setColorOpaque_I( getCableColor().mediumVariant ); + rh.setTexture( defa, defa, defa, defa, defa, defa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( getCableColor().whiteVariant ); + rh.setTexture( defb, defb, defb, defb, defb, defb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + + rh.setTexture( getTexture( getCableColor() ) ); + } + } + } + + if ( sides.size() != 2 || !nonLinear( sides ) || hasBuses ) + { + for (ForgeDirection of : connections) + { + renderSmartConection( x, y, z, rh, renderer, channelsOnSide[of.ordinal()], of ); + } + + rh.setTexture( getCoveredTexture( getCableColor() ) ); + rh.setBounds( 5, 5, 5, 11, 11, 11 ); + rh.renderBlock( x, y, z, renderer ); + } + else + { + ForgeDirection selectedSide = ForgeDirection.UNKNOWN; + + for (ForgeDirection of : connections) + { + selectedSide = of; + break; + } + + int channels = channelsOnSide[selectedSide.ordinal()]; + Icon def = getTexture( getCableColor() ); + Icon off = new OffsetIcon( def, 0, -12 ); + + Icon defa = new TaughtIcon( getChannelTex( channels, false ).getIcon(), -0.2f ); + Icon offa = new OffsetIcon( defa, 0, -12 ); + + Icon defb = new TaughtIcon( getChannelTex( channels, true ).getIcon(), -0.2f ); + Icon offb = new OffsetIcon( defb, 0, -12 ); + + switch (selectedSide) + { + case DOWN: + case UP: + renderer.setRenderBounds( 5 / 16.0, 0, 5 / 16.0, 11 / 16.0, 16 / 16.0, 11 / 16.0 ); + rh.setTexture( def, def, off, off, off, off ); + renderer.renderStandardBlock( rh.getBlock(), x, y, z ); + renderer.uvRotateTop = 0; + renderer.uvRotateBottom = 0; + renderer.uvRotateSouth = 3; + renderer.uvRotateEast = 3; + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + + Tessellator.instance.setColorOpaque_I( getCableColor().mediumVariant ); + rh.setTexture( defa, defa, offa, offa, offa, offa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( getCableColor().whiteVariant ); + rh.setTexture( defb, defb, offb, offb, offb, offb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + break; + case EAST: + case WEST: + rh.setTexture( off, off, off, off, def, def ); + renderer.uvRotateEast = 2; + renderer.uvRotateWest = 1; + renderer.uvRotateBottom = 2; + renderer.uvRotateTop = 1; + renderer.uvRotateSouth = 3; + renderer.uvRotateNorth = 0; + + AEBaseBlock blk = (AEBaseBlock) rh.getBlock(); + FlipableIcon ico = blk.getRendererInstance().getTexture( ForgeDirection.EAST ); + ico.setFlip( false, true ); + + renderer.setRenderBounds( 0, 5 / 16.0, 5 / 16.0, 16 / 16.0, 11 / 16.0, 11 / 16.0 ); + renderer.renderStandardBlock( rh.getBlock(), x, y, z ); + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + + Tessellator.instance.setColorOpaque_I( getCableColor().mediumVariant ); + rh.setTexture( offa, offa, offa, offa, defa, defa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( getCableColor().whiteVariant ); + rh.setTexture( offb, offb, offb, offb, defb, defb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + break; + case NORTH: + case SOUTH: + rh.setTexture( off, off, def, def, off, off ); + renderer.uvRotateTop = 3; + renderer.uvRotateBottom = 3; + renderer.uvRotateNorth = 1; + renderer.uvRotateSouth = 2; + renderer.uvRotateWest = 1; + renderer.setRenderBounds( 5 / 16.0, 5 / 16.0, 0, 11 / 16.0, 11 / 16.0, 16 / 16.0 ); + renderer.renderStandardBlock( rh.getBlock(), x, y, z ); + + Tessellator.instance.setBrightness( 15 << 20 | 15 << 5 ); + + Tessellator.instance.setColorOpaque_I( getCableColor().mediumVariant ); + rh.setTexture( offa, offa, defa, defa, offa, offa ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + + Tessellator.instance.setColorOpaque_I( getCableColor().whiteVariant ); + rh.setTexture( offb, offb, defb, defb, offb, offb ); + renderAllFaces( (AEBaseBlock) rh.getBlock(), x, y, z, renderer ); + break; + default: + break; + } + } + + renderer.uvRotateBottom = renderer.uvRotateEast = renderer.uvRotateNorth = renderer.uvRotateSouth = renderer.uvRotateTop = renderer.uvRotateWest = 0; + rh.setTexture( null ); + } +} diff --git a/parts/networking/PartQuartzFiber.java b/parts/networking/PartQuartzFiber.java new file mode 100644 index 00000000..80f1c35b --- /dev/null +++ b/parts/networking/PartQuartzFiber.java @@ -0,0 +1,146 @@ +package appeng.parts.networking; + +import java.util.EnumSet; +import java.util.Set; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraftforge.common.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import appeng.api.config.Actionable; +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.energy.IEnergyGridProvider; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartRenderHelper; +import appeng.api.util.AECableType; +import appeng.me.GridAccessException; +import appeng.me.helpers.AENetworkProxy; +import appeng.parts.AEBasePart; + +public class PartQuartzFiber extends AEBasePart implements IEnergyGridProvider +{ + + AENetworkProxy outerProxy = new AENetworkProxy( this, "outer", true ); + + public PartQuartzFiber(ItemStack is) { + super( PartQuartzFiber.class, is ); + proxy.setFlags( GridFlags.CANNOT_CARRY ); + } + + @Override + public void setPartHostInfo(ForgeDirection side, IPartHost host, TileEntity tile) + { + super.setPartHostInfo( side, host, tile ); + outerProxy.setValidSides( EnumSet.of( side ) ); + } + + @Override + public void readFromNBT(NBTTagCompound extra) + { + super.readFromNBT( extra ); + outerProxy.readFromNBT( extra ); + } + + @Override + public void writeToNBT(NBTTagCompound extra) + { + super.writeToNBT( extra ); + outerProxy.writeToNBT( extra ); + } + + @Override + public void addToWorld() + { + super.addToWorld(); + outerProxy.onReady(); + } + + @Override + public void removeFromWorld() + { + super.removeFromWorld(); + outerProxy.invalidate(); + } + + @Override + public IGridNode getExternalFacingNode() + { + return outerProxy.getNode(); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.GLASS; + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + Icon myIcon = is.getIconIndex(); + rh.setTexture( myIcon ); + rh.setBounds( 6, 6, 10, 10, 10, 16 ); + rh.renderBlock( x, y, z, renderer ); + rh.setTexture( null ); + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 6, 6, 10, 10, 10, 16 ); + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + GL11.glTranslated( -0.2, -0.3, 0.0 ); + + rh.setTexture( is.getIconIndex() ); + rh.setBounds( 6.0f, 6.0f, 5.0f, 10.0f, 10.0f, 11.0f ); + rh.renderInventoryBox( renderer ); + rh.setTexture( null ); + } + + @Override + public double extractAEPower(double amt, Actionable mode, Set seen) + { + double aquiredPower = 0; + + try + { + IEnergyGrid eg = proxy.getEnergy(); + aquiredPower += eg.extractAEPower( amt - aquiredPower, mode, seen ); + } + catch (GridAccessException e) + { + // :P + } + + try + { + IEnergyGrid eg = outerProxy.getEnergy(); + aquiredPower += eg.extractAEPower( amt - aquiredPower, mode, seen ); + } + catch (GridAccessException e) + { + // :P + } + + return aquiredPower; + } + + @Override + public int cableConnectionRenderTo() + { + return 16; + } + +} diff --git a/parts/reporting/PartConversionMonitor.java b/parts/reporting/PartConversionMonitor.java new file mode 100644 index 00000000..b2e36718 --- /dev/null +++ b/parts/reporting/PartConversionMonitor.java @@ -0,0 +1,17 @@ +package appeng.parts.reporting; + +import net.minecraft.item.ItemStack; +import appeng.client.texture.CableBusTextures; + +public class PartConversionMonitor extends PartStorageMonitor +{ + + public PartConversionMonitor(ItemStack is) { + super( PartConversionMonitor.class, is ); + frontBright = CableBusTextures.PartConvMonitor_Bright; + frontColored = CableBusTextures.PartConvMonitor_Colored; + frontDark = CableBusTextures.PartConvMonitor_Dark; + frontSolid = CableBusTextures.PartConvMonitor_Solid; + } + +} diff --git a/parts/reporting/PartCraftingMonitor.java b/parts/reporting/PartCraftingMonitor.java new file mode 100644 index 00000000..344b6ef7 --- /dev/null +++ b/parts/reporting/PartCraftingMonitor.java @@ -0,0 +1,17 @@ +package appeng.parts.reporting; + +import net.minecraft.item.ItemStack; +import appeng.client.texture.CableBusTextures; + +public class PartCraftingMonitor extends PartMonitor +{ + + public PartCraftingMonitor(ItemStack is) { + super( PartCraftingMonitor.class, is ); + frontBright = CableBusTextures.PartCraftingMonitor_Bright; + frontColored = CableBusTextures.PartCraftingMonitor_Colored; + frontDark = CableBusTextures.PartCraftingMonitor_Dark; + frontSolid = CableBusTextures.PartCraftingMonitor_Solid; + } + +} diff --git a/parts/reporting/PartCraftingTerminal.java b/parts/reporting/PartCraftingTerminal.java new file mode 100644 index 00000000..e4af3e00 --- /dev/null +++ b/parts/reporting/PartCraftingTerminal.java @@ -0,0 +1,17 @@ +package appeng.parts.reporting; + +import net.minecraft.item.ItemStack; +import appeng.client.texture.CableBusTextures; + +public class PartCraftingTerminal extends PartMonitor +{ + + public PartCraftingTerminal(ItemStack is) { + super( PartCraftingTerminal.class, is ); + frontBright = CableBusTextures.PartCraftingTerm_Bright; + frontColored = CableBusTextures.PartCraftingTerm_Colored; + frontDark = CableBusTextures.PartCraftingTerm_Dark; + frontSolid = CableBusTextures.PartCraftingTerm_Solid; + } + +} diff --git a/parts/reporting/PartDarkMonitor.java b/parts/reporting/PartDarkMonitor.java new file mode 100644 index 00000000..173e5ab3 --- /dev/null +++ b/parts/reporting/PartDarkMonitor.java @@ -0,0 +1,57 @@ +package appeng.parts.reporting; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; + +public class PartDarkMonitor extends PartMonitor +{ + + public PartDarkMonitor(ItemStack is) { + super( PartDarkMonitor.class, is ); + + notLightSource = false; + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + rh.renderInventoryBox( renderer ); + + rh.setInvColor( getColor().mediumVariant ); + rh.renderInventoryFace( frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderBlock( x, y, z, renderer ); + + if ( getLightLevel() > 0 ) + { + int l = 13; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + } + + Tessellator.instance.setColorOpaque_I( getColor().mediumVariant ); + rh.renderFace( x, y, z, frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderBlock( x, y, z, renderer ); + } + +} diff --git a/parts/reporting/PartMonitor.java b/parts/reporting/PartMonitor.java new file mode 100644 index 00000000..38f349b4 --- /dev/null +++ b/parts/reporting/PartMonitor.java @@ -0,0 +1,225 @@ +package appeng.parts.reporting; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Vec3; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IPartMonitor; +import appeng.api.networking.GridFlags; +import appeng.api.networking.events.MENetworkBootingStatusChange; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.parts.IPartCollsionHelper; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; +import appeng.me.GridAccessException; +import appeng.parts.AEBasePart; +import appeng.util.Platform; + +public class PartMonitor extends AEBasePart implements IPartMonitor +{ + + CableBusTextures frontSolid = CableBusTextures.PartMonitor_Solid; + CableBusTextures frontDark = CableBusTextures.PartMonitor_Colored; + CableBusTextures frontBright = CableBusTextures.PartMonitor_Bright; + CableBusTextures frontColored = CableBusTextures.PartMonitor_Colored; + + boolean notLightSource = !this.getClass().equals( PartMonitor.class ); + + final int POWERED_FLAG = 1; + final int BOOTING_FLAG = 2; + final int CHANNEL_FLAG = 4; + + int clientFlags = 0; // sent as byte. + + @MENetworkEventSubscribe + public void bootingRender(MENetworkBootingStatusChange c) + { + if ( notLightSource ) + getHost().markForUpdate(); + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + getHost().markForUpdate(); + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + super.writeToStream( data ); + clientFlags = 0; + + try + { + if ( proxy.getEnergy().isNetworkPowered() ) + clientFlags = clientFlags | POWERED_FLAG; + + if ( proxy.getPath().isNetworkBooting() ) + clientFlags = clientFlags | BOOTING_FLAG; + + if ( proxy.getNode().meetsChannelRequirements() ) + clientFlags = clientFlags | CHANNEL_FLAG; + } + catch (GridAccessException e) + { + // um.. nothing. + } + + data.writeByte( (byte) clientFlags ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + super.readFromStream( data ); + int oldFlags = clientFlags; + clientFlags = data.readByte(); + if ( clientFlags == oldFlags ) + return false; + return true; + } + + @Override + public int getLightLevel() + { + return isPowered() ? (notLightSource ? 9 : 15) : 0; + } + + @Override + public boolean isPowered() + { + try + { + if ( Platform.isServer() ) + return proxy.getEnergy().isNetworkPowered(); + else + return ((clientFlags & POWERED_FLAG) == POWERED_FLAG); + } + catch (GridAccessException e) + { + return false; + } + } + + public PartMonitor(ItemStack is) { + super( PartMonitor.class, is ); + } + + protected PartMonitor(Class c, ItemStack is) { + super( c, is ); + if ( notLightSource ) + proxy.setFlags( GridFlags.REQURE_CHANNEL ); + else + proxy.setIdlePowerUsage( 1.0 / 16.0 ); // lights drain a little bit. + + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + rh.renderInventoryBox( renderer ); + + rh.setInvColor( getColor().whiteVariant ); + rh.renderInventoryFace( frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setInvColor( getColor().mediumVariant ); + rh.renderInventoryFace( frontDark.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setInvColor( getColor().blackVariant ); + rh.renderInventoryFace( frontColored.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderBlock( x, y, z, renderer ); + + if ( getLightLevel() > 0 ) + { + int l = 13; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + } + + Tessellator.instance.setColorOpaque_I( getColor().whiteVariant ); + rh.renderFace( x, y, z, frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + Tessellator.instance.setColorOpaque_I( getColor().mediumVariant ); + rh.renderFace( x, y, z, frontDark.getIcon(), ForgeDirection.SOUTH, renderer ); + + Tessellator.instance.setColorOpaque_I( getColor().blackVariant ); + rh.renderFace( x, y, z, frontColored.getIcon(), ForgeDirection.SOUTH, renderer ); + + if ( notLightSource ) + { + rh.setTexture( CableBusTextures.PartMonitorSidesStatus.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorBack.getIcon(), frontSolid.getIcon(), CableBusTextures.PartMonitorSidesStatus.getIcon(), + CableBusTextures.PartMonitorSidesStatus.getIcon() ); + } + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderBlock( x, y, z, renderer ); + + if ( notLightSource ) + { + boolean hasChan = (clientFlags & (POWERED_FLAG | CHANNEL_FLAG)) == (POWERED_FLAG | CHANNEL_FLAG); + boolean hasPower = (clientFlags & POWERED_FLAG) == POWERED_FLAG; + + if ( hasChan ) + { + int l = 14; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( getColor().blackVariant ); + } + else if ( hasPower ) + { + int l = 9; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + Tessellator.instance.setColorOpaque_I( getColor().whiteVariant ); + } + else + { + Tessellator.instance.setBrightness( 0 ); + Tessellator.instance.setColorOpaque_I( 0x000000 ); + } + + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.EAST, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.WEST, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.UP, renderer ); + rh.renderFace( x, y, z, CableBusTextures.PartMonitorSidesStatusLights.getIcon(), ForgeDirection.DOWN, renderer ); + } + + } + + @Override + public void getBoxes(IPartCollsionHelper bch) + { + bch.addBox( 2, 2, 14, 14, 14, 16 ); + bch.addBox( 4, 4, 13, 12, 12, 14 ); + } + + @Override + public boolean onActivate(EntityPlayer player, Vec3 pos) + { + return false; + } + +} diff --git a/parts/reporting/PartPatternTerminal.java b/parts/reporting/PartPatternTerminal.java new file mode 100644 index 00000000..6cbd6763 --- /dev/null +++ b/parts/reporting/PartPatternTerminal.java @@ -0,0 +1,17 @@ +package appeng.parts.reporting; + +import net.minecraft.item.ItemStack; +import appeng.client.texture.CableBusTextures; + +public class PartPatternTerminal extends PartMonitor +{ + + public PartPatternTerminal(ItemStack is) { + super( PartPatternTerminal.class, is ); + frontBright = CableBusTextures.PartPatternTerm_Bright; + frontColored = CableBusTextures.PartPatternTerm_Colored; + frontDark = CableBusTextures.PartPatternTerm_Dark; + frontSolid = CableBusTextures.PartPatternTerm_Solid; + } + +} diff --git a/parts/reporting/PartSemiDarkMonitor.java b/parts/reporting/PartSemiDarkMonitor.java new file mode 100644 index 00000000..a09c553f --- /dev/null +++ b/parts/reporting/PartSemiDarkMonitor.java @@ -0,0 +1,63 @@ +package appeng.parts.reporting; + +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.parts.IPartRenderHelper; +import appeng.client.texture.CableBusTextures; + +public class PartSemiDarkMonitor extends PartMonitor +{ + + public PartSemiDarkMonitor(ItemStack is) { + super( PartSemiDarkMonitor.class, is ); + + notLightSource = false; + } + + @Override + public void renderInventory(IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + rh.renderInventoryBox( renderer ); + + int light = getColor().whiteVariant; + int dark = getColor().mediumVariant; + rh.setInvColor( (((((light >> 16) & 0xff) + ((dark >> 16) & 0xff)) / 2) << 16) | (((((light >> 8) & 0xff) + ((dark >> 8) & 0xff)) / 2) << 8) + | ((((light) & 0xff) + ((dark) & 0xff)) / 2) ); + rh.renderInventoryFace( frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderInventoryBox( renderer ); + } + + @Override + public void renderStatic(int x, int y, int z, IPartRenderHelper rh, RenderBlocks renderer) + { + rh.setTexture( CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorBack.getIcon(), + frontSolid.getIcon(), CableBusTextures.PartMonitorSides.getIcon(), CableBusTextures.PartMonitorSides.getIcon() ); + + rh.setBounds( 2, 2, 14, 14, 14, 16 ); + rh.renderBlock( x, y, z, renderer ); + + if ( getLightLevel() > 0 ) + { + int l = 13; + Tessellator.instance.setBrightness( l << 20 | l << 4 ); + } + + int light = getColor().whiteVariant; + int dark = getColor().mediumVariant; + Tessellator.instance.setColorOpaque( (((light >> 16) & 0xff) + ((dark >> 16) & 0xff)) / 2, (((light >> 8) & 0xff) + ((dark >> 8) & 0xff)) / 2, + (((light) & 0xff) + ((dark) & 0xff)) / 2 ); + rh.renderFace( x, y, z, frontBright.getIcon(), ForgeDirection.SOUTH, renderer ); + + rh.setBounds( 4, 4, 13, 12, 12, 14 ); + rh.renderBlock( x, y, z, renderer ); + } + +} diff --git a/parts/reporting/PartStorageMonitor.java b/parts/reporting/PartStorageMonitor.java new file mode 100644 index 00000000..84f446d3 --- /dev/null +++ b/parts/reporting/PartStorageMonitor.java @@ -0,0 +1,37 @@ +package appeng.parts.reporting; + +import net.minecraft.item.ItemStack; +import appeng.api.implementations.IPartStorageMonitor; +import appeng.api.storage.data.IAEStack; +import appeng.client.texture.CableBusTextures; + +public class PartStorageMonitor extends PartMonitor implements IPartStorageMonitor +{ + + protected PartStorageMonitor(Class myClass, ItemStack is) { + super( myClass, is ); + } + + public PartStorageMonitor(ItemStack is) { + super( PartStorageMonitor.class, is ); + frontBright = CableBusTextures.PartStorageMonitor_Bright; + frontColored = CableBusTextures.PartStorageMonitor_Colored; + frontDark = CableBusTextures.PartStorageMonitor_Dark; + frontSolid = CableBusTextures.PartStorageMonitor_Solid; + } + + @Override + public IAEStack getDisplayed() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isLocked() + { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/parts/reporting/PartTerminal.java b/parts/reporting/PartTerminal.java new file mode 100644 index 00000000..60d2ee8f --- /dev/null +++ b/parts/reporting/PartTerminal.java @@ -0,0 +1,67 @@ +package appeng.parts.reporting; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Vec3; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.storage.IMEMonitor; +import appeng.client.texture.CableBusTextures; +import appeng.core.sync.GuiBridge; +import appeng.me.GridAccessException; +import appeng.util.Platform; + +public class PartTerminal extends PartMonitor implements IStorageMonitorable +{ + + public PartTerminal(ItemStack is) { + super( PartTerminal.class, is ); + frontBright = CableBusTextures.PartTerminal_Bright; + frontColored = CableBusTextures.PartTerminal_Colored; + frontDark = CableBusTextures.PartTerminal_Dark; + frontSolid = CableBusTextures.PartTerminal_Solid; + } + + @Override + public boolean onActivate(EntityPlayer player, Vec3 pos) + { + if ( !player.isSneaking() ) + { + if ( Platform.isClient() ) + return true; + + Platform.openGUI( player, getHost().getTile(), side, GuiBridge.GUI_ME ); + return true; + } + + return false; + } + + @Override + public IMEMonitor getFluidInventory() + { + try + { + return proxy.getStorage().getFluidInventory(); + } + catch (GridAccessException e) + { + // err nope? + } + return null; + } + + @Override + public IMEMonitor getItemInventory() + { + try + { + return proxy.getStorage().getItemInventory(); + } + catch (GridAccessException e) + { + // err nope? + } + return null; + } + +} diff --git a/recipes/AEShapedOreRecipe.java b/recipes/AEShapedOreRecipe.java new file mode 100644 index 00000000..b7e7ce92 --- /dev/null +++ b/recipes/AEShapedOreRecipe.java @@ -0,0 +1,13 @@ +package appeng.recipes; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.ShapedOreRecipe; + +public class AEShapedOreRecipe extends ShapedOreRecipe +{ + + public AEShapedOreRecipe(ItemStack result, Object... recipe) { + super( result, recipe ); + + } +} diff --git a/recipes/AEShapedQuartzRecipe.java b/recipes/AEShapedQuartzRecipe.java new file mode 100644 index 00000000..14d545f7 --- /dev/null +++ b/recipes/AEShapedQuartzRecipe.java @@ -0,0 +1,276 @@ +package appeng.recipes; + +import java.util.ArrayList; +import java.util.HashMap; + +import net.minecraft.block.Block; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.oredict.OreDictionary; +import appeng.api.AEApi; + +/* + * Basically the ore dictionary crafting recipe, with a slight twist + * of adding quartz to the lists even tho they are not in the ore dictionary. + * + * Yes this is silly, but it seemed simpler then re-writing half the class to make a simple alteration. + */ + +public class AEShapedQuartzRecipe implements IRecipe +{ + + // Added in for future ease of change, but hard coded for now. + private static final int MAX_CRAFT_GRID_WIDTH = 3; + private static final int MAX_CRAFT_GRID_HEIGHT = 3; + + private ItemStack output = null; + private Object[] input = null; + private int width = 0; + private int height = 0; + private boolean mirrored = true; + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public Object[] getIngredients() + { + return input; + } + + public AEShapedQuartzRecipe(ItemStack result, boolean dust, Object... recipe) { + output = result.copy(); + + String shape = ""; + int idx = 0; + + if ( recipe[idx] instanceof Boolean ) + { + mirrored = (Boolean) recipe[idx]; + if ( recipe[idx + 1] instanceof Object[] ) + { + recipe = (Object[]) recipe[idx + 1]; + } else + { + idx = 1; + } + } + + if ( recipe[idx] instanceof String[] ) + { + String[] parts = ((String[]) recipe[idx++]); + + for (String s : parts) + { + width = s.length(); + shape += s; + } + + height = parts.length; + } else + { + while (recipe[idx] instanceof String) + { + String s = (String) recipe[idx++]; + shape += s; + width = s.length(); + height++; + } + } + + if ( width * height != shape.length() ) + { + String ret = "Invalid shaped ore recipe: "; + for (Object tmp : recipe) + { + ret += tmp + ", "; + } + ret += output; + throw new RuntimeException( ret ); + } + + HashMap itemMap = new HashMap(); + + for (; idx < recipe.length; idx += 2) + { + Character chr = (Character) recipe[idx]; + Object in = recipe[idx + 1]; + + if ( in instanceof ItemStack ) + { + itemMap.put( chr, ((ItemStack) in).copy() ); + } else if ( in instanceof Item ) + { + itemMap.put( chr, new ItemStack( (Item) in ) ); + } else if ( in instanceof Block ) + { + itemMap.put( chr, new ItemStack( (Block) in, 1, OreDictionary.WILDCARD_VALUE ) ); + } else if ( in instanceof String ) + { + ArrayList is = OreDictionary.getOres( (String) in ); + ArrayList copy = new ArrayList(); + copy.addAll( is ); + + if ( in.equals( "crystalQuartz" ) || in.equals( "dustQuartz" ) ) + { + if ( dust ) + { + copy.add( AEApi.instance().materials().materialCertusQuartzDust.stack( 1 ) ); + copy.add( AEApi.instance().materials().materialNetherQuartzDust.stack( 1 ) ); + } else + { + copy.add( AEApi.instance().materials().materialCertusQuartzCrystal.stack( 1 ) ); + copy.add( new ItemStack( Item.netherQuartz ) ); + } + } + + itemMap.put( chr, copy ); + } else + { + String ret = "Invalid shaped ore recipe: "; + for (Object tmp : recipe) + { + ret += tmp + ", "; + } + ret += output; + throw new RuntimeException( ret ); + } + } + + input = new Object[width * height]; + int x = 0; + for (char chr : shape.toCharArray()) + { + input[x++] = itemMap.get( chr ); + } + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting var1) + { + return output.copy(); + } + + @Override + public int getRecipeSize() + { + return input.length; + } + + @Override + public ItemStack getRecipeOutput() + { + return output; + } + + @Override + public boolean matches(InventoryCrafting inv, World world) + { + for (int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++) + { + for (int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y) + { + if ( checkMatch( inv, x, y, false ) ) + { + return true; + } + + if ( mirrored && checkMatch( inv, x, y, true ) ) + { + return true; + } + } + } + + return false; + } + + private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror) + { + for (int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++) + { + for (int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++) + { + int subX = x - startX; + int subY = y - startY; + Object target = null; + + if ( subX >= 0 && subY >= 0 && subX < width && subY < height ) + { + if ( mirror ) + { + target = input[width - subX - 1 + subY * width]; + } else + { + target = input[subX + subY * width]; + } + } + + ItemStack slot = inv.getStackInRowAndColumn( x, y ); + + if ( target instanceof ItemStack ) + { + if ( !checkItemEquals( (ItemStack) target, slot ) ) + { + return false; + } + } else if ( target instanceof ArrayList ) + { + boolean matched = false; + + for (ItemStack item : (ArrayList) target) + { + matched = matched || checkItemEquals( item, slot ); + } + + if ( !matched ) + { + return false; + } + } else if ( target == null && slot != null ) + { + return false; + } + } + } + + return true; + } + + private boolean checkItemEquals(ItemStack target, ItemStack input) + { + if ( input == null && target != null || input != null && target == null ) + { + return false; + } + return (target.itemID == input.itemID && (target.getItemDamage() == OreDictionary.WILDCARD_VALUE || target + .getItemDamage() == input.getItemDamage())); + } + + public AEShapedQuartzRecipe setMirrored(boolean mirror) + { + mirrored = mirror; + return this; + } + + /** + * Returns the input for this recipe, any mod accessing this value should + * never manipulate the values in this array as it will effect the recipe + * itself. + * + * @return The recipes input vales. + */ + public Object[] getInput() + { + return this.input; + } +} diff --git a/recipes/AEShapelessOreRecipe.java b/recipes/AEShapelessOreRecipe.java new file mode 100644 index 00000000..c1528173 --- /dev/null +++ b/recipes/AEShapelessOreRecipe.java @@ -0,0 +1,12 @@ +package appeng.recipes; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.ShapelessOreRecipe; + +public class AEShapelessOreRecipe extends ShapelessOreRecipe +{ + + public AEShapelessOreRecipe(ItemStack output, Object... t) { + super( output, t ); + } +} diff --git a/recipes/Recipe.java b/recipes/Recipe.java new file mode 100644 index 00000000..359e4556 --- /dev/null +++ b/recipes/Recipe.java @@ -0,0 +1,36 @@ +package appeng.recipes; + +import java.util.Iterator; + +public class Recipe +{ + + final int size; + final RecipeType type; + final RecipeItem items[]; + + public Recipe(RecipeType rt, Iterator ilist) throws RecipeError { + type = rt; + items = new RecipeItem[rt.getSize()]; + + int itemCount = 0; + while (itemCount < rt.getSize() && ilist.hasNext()) + { + items[itemCount++] = ilist.next(); + } + + if ( ilist.hasNext() ) + throw new RecipeError( "Invalid Number of Items in recipe." ); + + if ( rt.isShaped() ) + { + if ( itemCount != rt.getSize() ) + throw new RecipeError( "Invalid Number of Items in recipe." ); + + size = rt.getSize(); + } + else + size = itemCount; + } + +} diff --git a/recipes/RecipeError.java b/recipes/RecipeError.java new file mode 100644 index 00000000..74fbe067 --- /dev/null +++ b/recipes/RecipeError.java @@ -0,0 +1,12 @@ +package appeng.recipes; + +public class RecipeError extends Exception +{ + + private static final long serialVersionUID = -6602870588617670262L; + + public RecipeError(String n) { + super( n ); + } + +} diff --git a/recipes/RecipeItem.java b/recipes/RecipeItem.java new file mode 100644 index 00000000..8a35520d --- /dev/null +++ b/recipes/RecipeItem.java @@ -0,0 +1,36 @@ +package appeng.recipes; + +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +public class RecipeItem +{ + + final private ItemStack is[]; + final private int oreID; + + RecipeItem(ItemStack in) { + oreID = -1; + is = new ItemStack[1]; + is[0] = in; + } + + RecipeItem(String oreName) { + oreID = OreDictionary.getOreID( oreName ); + List ores = OreDictionary.getOres( oreID ); + is = ores.toArray( new ItemStack[ores.size()] ); + } + + int getOreID() + { + return oreID; + } + + ItemStack[] getValidItems() + { + return is; + } + +} diff --git a/recipes/RecipeParser.java b/recipes/RecipeParser.java new file mode 100644 index 00000000..d9a4deff --- /dev/null +++ b/recipes/RecipeParser.java @@ -0,0 +1,7 @@ +package appeng.recipes; + + +public class RecipeParser +{ + +} diff --git a/recipes/RecipeType.java b/recipes/RecipeType.java new file mode 100644 index 00000000..14d4c5ee --- /dev/null +++ b/recipes/RecipeType.java @@ -0,0 +1,51 @@ +package appeng.recipes; + +public enum RecipeType +{ + // Shapeless + Shape0x0, + // Shaped 1x1 + Shape1x1(1, 1), + // Shaped 2x2 + Shape1x2(1, 2), Shape2x1(2, 1), Shape2x2(2, 2), + // Shaped 3x3 + Shape2x3(2, 3), Shape3x2(3, 2), Shape3x3(3, 3); + + boolean shapeless; + final int width; + final int height; + final int size; + + private RecipeType(int w, int h) { + width = w; + height = h; + size = w * h; + shapeless = false; + } + + private RecipeType() { + this( 3, 3 ); + shapeless = true; + } + + public boolean isShaped() + { + return shapeless; + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public int getSize() + { + return size; + } + +} diff --git a/recipes/ores/IOreListener.java b/recipes/ores/IOreListener.java new file mode 100644 index 00000000..1d57196e --- /dev/null +++ b/recipes/ores/IOreListener.java @@ -0,0 +1,17 @@ +package appeng.recipes.ores; + +import net.minecraft.item.ItemStack; + +public interface IOreListener +{ + + /** + * Called with various items registered in the dictionary. + * AppEng.oreDictionary.observe(...) to register them. + * + * @param Name + * @param item + */ + void oreRegistered(String Name, ItemStack item); + +} diff --git a/recipes/ores/OreDictionaryHandler.java b/recipes/ores/OreDictionaryHandler.java new file mode 100644 index 00000000..98a90950 --- /dev/null +++ b/recipes/ores/OreDictionaryHandler.java @@ -0,0 +1,61 @@ +package appeng.recipes.ores; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.oredict.OreDictionary; + +public class OreDictionaryHandler +{ + + public static final OreDictionaryHandler instance = new OreDictionaryHandler(); + + private List ol = new ArrayList(); + + /** + * Just limit what items are sent to the final listeners, I got sick of strange items showing up... + * + * @param name + * @return + */ + private boolean shouldCare(String name) + { + return true; + } + + @ForgeSubscribe + public void onOreDictionaryRegister(OreDictionary.OreRegisterEvent event) + { + if ( shouldCare( event.Name ) ) + { + for (IOreListener v : ol) + v.oreRegistered( event.Name, event.Ore ); + } + } + + /** + * Adds a new IOreListener and immediately notifies it of any previous ores, any ores added latter will be added at + * that point. + * + * @param n + */ + public void observe(IOreListener n) + { + ol.add( n ); + + // notify the listener of any ore already in existance. + for (String name : OreDictionary.getOreNames()) + { + if ( shouldCare( name ) ) + { + for (ItemStack item : OreDictionary.getOres( name )) + { + n.oreRegistered( name, item ); + } + } + } + } + +} diff --git a/server/AECommand.java b/server/AECommand.java new file mode 100644 index 00000000..552b741f --- /dev/null +++ b/server/AECommand.java @@ -0,0 +1,116 @@ +package appeng.server; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.server.MinecraftServer; +import appeng.services.Profiler; + +public class AECommand extends CommandBase +{ + + public AECommand(MinecraftServer server) { + } + + @Override + public String getCommandName() + { + return "ae"; + } + + @Override + public String getCommandUsage(ICommandSender icommandsender) + { + return "commands.ae.usage"; + } + + @Override + public int getRequiredPermissionLevel() + { + return 2; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) + { + if ( args.length == 0 ) + { + throw new WrongUsageException( "commands.ae.usage" ); + } + else if ( "help".equals( args[0] ) ) + { + throw new WrongUsageException( "commands.ae.usage" ); + } + else if ( "profile".equals( args[0] ) ) + { + if ( args.length > 1 && "start".equals( args[1] ) ) + beginProfile( sender, args ); + else if ( args.length > 1 && "stop".equals( args[1] ) ) + endProfile( sender, args ); + else + throw new WrongUsageException( "commands.ae.profile.usage" ); + } + else + { + throw new WrongUsageException( "commands.ae.usage" ); + } + } + + private void endProfile(ICommandSender sender, String[] args) + { + if ( Profiler.instance == null ) + { + throw new CommandException( "commands.ae.profiling.nojdk" ); + } + + if ( Profiler.instance.isRunning ) + { + if ( Profiler.instance.profile ) + { + Profiler.instance.profile = false; + synchronized (Profiler.instance.lock) + { + Profiler.instance.lock.notify(); + } + } + else + throw new CommandException( "commands.ae.profiling.inactive" ); + } + else + throw new CommandException( "commands.ae.profiling.nojdk" ); + } + + private void beginProfile(ICommandSender sender, String[] args) + { + if ( Profiler.instance == null ) + { + throw new CommandException( "commands.ae.profiling.nojdk" ); + } + + if ( Profiler.instance.isRunning ) + { + if ( Profiler.instance.profile ) + throw new CommandException( "commands.ae.profiling.active" ); + else + { + Profiler.instance.profile = true; + synchronized (Profiler.instance.lock) + { + Profiler.instance.lock.notify(); + } + } + } + else + throw new CommandException( "commands.ae.profiling.nojdk" ); + } + + /** + * wtf? + */ + @Override + public int compareTo(Object arg0) + { + return 1; + } +} diff --git a/server/AccessType.java b/server/AccessType.java new file mode 100644 index 00000000..6cceb5c6 --- /dev/null +++ b/server/AccessType.java @@ -0,0 +1,34 @@ +package appeng.server; + +public enum AccessType +{ + /** + * allows basic access to manipulate the block via gui, or other. + */ + BLOCK_ACCESS, + + /** + * Can player deposit items into the network. + */ + NETWORK_DEPOSIT, + + /** + * can player withdraw items from the network. + */ + NETWORK_WITHDRAW, + + /** + * can player issue crafting requests? + */ + NETWORK_CRAFT, + + /** + * can player add new blocks to the network. + */ + NETWORK_BUILD, + + /** + * can player manipulate security settings. + */ + NETWORK_SECURITY +} diff --git a/server/Security.java b/server/Security.java new file mode 100644 index 00000000..a5fbb5e8 --- /dev/null +++ b/server/Security.java @@ -0,0 +1,14 @@ +package appeng.server; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; + +public class Security +{ + + public static boolean hasPermissions(TileEntity myTile, EntityPlayer player, AccessType blockAccess) + { + return true; + } + +} diff --git a/server/ServerHelper.java b/server/ServerHelper.java new file mode 100644 index 00000000..2ea7705a --- /dev/null +++ b/server/ServerHelper.java @@ -0,0 +1,75 @@ +package appeng.server; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.packet.Packet; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import appeng.block.AEBaseBlock; +import appeng.core.CommonHelper; +import appeng.util.Platform; +import cpw.mods.fml.common.FMLCommonHandler; + +public class ServerHelper extends CommonHelper +{ + + @Override + public List getPlayers() + { + if ( !Platform.isClient() ) + { + MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); + + if ( server != null ) + return server.getConfigurationManager().playerEntityList; + } + + return new ArrayList(); + } + + @Override + public void sendToAllNearExcept(EntityPlayer p, double x, double y, double z, double dist, World w, Packet packet) + { + if ( Platform.isClient() ) + return; + + for (EntityPlayer o : getPlayers()) + { + EntityPlayerMP entityplayermp = (EntityPlayerMP) o; + + if ( entityplayermp != p && entityplayermp.worldObj == w ) + { + double dX = x - entityplayermp.posX; + double dY = y - entityplayermp.posY; + double dZ = z - entityplayermp.posZ; + + if ( dX * dX + dY * dY + dZ * dZ < dist * dist ) + { + entityplayermp.playerNetServerHandler.sendPacketToPlayer( packet ); + } + } + } + } + + @Override + public void init() + { + + } + + @Override + public World getWorld() + { + throw new RuntimeException( "This is a server..." ); + } + + @Override + public void bindTileEntitySpecialRenderer(Class tile, AEBaseBlock blk) + { + throw new RuntimeException( "This is a server..." ); + } + +} diff --git a/services/Profiler.java b/services/Profiler.java new file mode 100644 index 00000000..43cb8371 --- /dev/null +++ b/services/Profiler.java @@ -0,0 +1,277 @@ +package appeng.services; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.commons.lang3.StringUtils; + +import appeng.core.AELog; + +public class Profiler implements Runnable +{ + + public static Profiler instance = null; + public boolean profile = false; + public boolean isRunning = true; + public final Object lock = new Object(); + + public static String getCommandOutput(String command) + { + String output = null; // the string to return + + Process process = null; + BufferedReader reader = null; + InputStreamReader streamReader = null; + InputStream stream = null; + + try + { + process = Runtime.getRuntime().exec( command ); + + stream = process.getInputStream(); + streamReader = new InputStreamReader( stream ); + reader = new BufferedReader( streamReader ); + + String currentLine = null; + StringBuilder commandOutput = new StringBuilder(); + while ((currentLine = reader.readLine()) != null) + { + commandOutput.append( currentLine ); + } + + int returnCode = process.waitFor(); + if ( returnCode == 0 ) + { + output = commandOutput.toString(); + } + + } + catch (IOException e) + { + output = null; + } + catch (InterruptedException e) + { + } + finally + { + + if ( stream != null ) + { + try + { + stream.close(); + } + catch (IOException e) + { + } + } + if ( streamReader != null ) + { + try + { + streamReader.close(); + } + catch (IOException e) + { + } + } + if ( reader != null ) + { + try + { + streamReader.close(); + } + catch (IOException e) + { + } + } + } + + return output; + } + + private String findJDK() + { + if ( System.getProperty( "os.name" ).contains( "win" ) || System.getProperty( "os.name" ).contains( "Win" ) ) + { + String path = getCommandOutput( "where javac" ); + if ( path == null || path.isEmpty() ) + { + + } + else + { + File javacFile = new File( path ); + File jdkInstallationDir = javacFile.getParentFile().getParentFile(); + return jdkInstallationDir.getPath(); + } + } + else + { + String response = getCommandOutput( "whereis javac" ); + if ( response == null ) + { + + } + else + { + int pathStartIndex = response.indexOf( '/' ); + if ( pathStartIndex == -1 ) + { + } + else + { + String path = response.substring( pathStartIndex, response.length() ); + File javacFile = new File( path ); + File jdkInstallationDir = javacFile.getParentFile().getParentFile(); + return jdkInstallationDir.getPath(); + } + } + } + return null; + } + + Class ProfilingSettingsPresets; + Class CPUResultsSnapshot; + Class StackTraceSnapshotBuilder; + Class LoadedSnapshot; + Class Lookup; + Class LookupProvider; + Class ResultsSnapshot; + Class ProfilingSettings; + + Method addStacktrace; + Method createSnapshot; + Method createCPUPreset; + Method save; + Constructor LoadedSnapshot_Constructor; + + @Override + public void run() + { + instance = this; + + try + { + String JDKpath = findJDK(); + + String root = StringUtils.join( new String[] { JDKpath, "lib", "visualvm" }, File.separator ); + String Base = StringUtils.join( new String[] { root, "profiler", "modules", "" }, File.separator ); + String BaseB = StringUtils.join( new String[] { root, "platform", "lib", "" }, File.separator ); + + File a = new File( Base + "org-netbeans-lib-profiler.jar" ); + File b = new File( Base + "org-netbeans-lib-profiler-common.jar" ); + File c = new File( Base + "org-netbeans-modules-profiler.jar" ); + File d = new File( BaseB + "org-openide-util.jar" ); + File e = new File( BaseB + "org-openide-util-lookup.jar" ); + + ClassLoader cl = URLClassLoader.newInstance( new URL[] { a.toURI().toURL(), b.toURI().toURL(), c.toURI().toURL(), d.toURI().toURL(), + e.toURI().toURL() } ); + + ProfilingSettingsPresets = cl.loadClass( "org.netbeans.lib.profiler.common.ProfilingSettingsPresets" ); + ProfilingSettings = cl.loadClass( "org.netbeans.lib.profiler.common.ProfilingSettings" ); + CPUResultsSnapshot = cl.loadClass( "org.netbeans.lib.profiler.results.cpu.CPUResultsSnapshot" ); + ResultsSnapshot = cl.loadClass( "org.netbeans.lib.profiler.results.ResultsSnapshot" ); + StackTraceSnapshotBuilder = cl.loadClass( "org.netbeans.lib.profiler.results.cpu.StackTraceSnapshotBuilder" ); + LoadedSnapshot = cl.loadClass( "org.netbeans.modules.profiler.LoadedSnapshot" ); + Lookup = cl.loadClass( "org.openide.util.Lookup" ); + + for (Class dc : Lookup.getDeclaredClasses()) + { + if ( dc.getSimpleName().equals( "Provider" ) ) + LookupProvider = dc; + } + + if ( LookupProvider == null ) + throw new ClassNotFoundException( "Lookup.Provider" ); + + addStacktrace = StackTraceSnapshotBuilder.getMethod( "addStacktrace", ThreadInfo[].class, long.class ); + createSnapshot = StackTraceSnapshotBuilder.getMethod( "createSnapshot", long.class ); + createCPUPreset = ProfilingSettingsPresets.getMethod( "createCPUPreset" ); + save = LoadedSnapshot.getMethod( "save", DataOutputStream.class ); + LoadedSnapshot_Constructor = LoadedSnapshot.getConstructor( ResultsSnapshot, ProfilingSettings, File.class, LookupProvider ); + } + catch (Throwable t) + { + isRunning = false; + AELog.info( "Unable to find/load JDK, profiling disabled." ); + return; + } + + int limit = 0; + while (isRunning) + { + if ( profile ) + { + limit = 9000; + + try + { + Object StackTraceSnapshotBuilder_Instance = StackTraceSnapshotBuilder.newInstance(); + ThreadMXBean mxBean = ManagementFactory.getThreadMXBean(); + + while (profile) + { + if ( limit-- < 0 ) + profile = false; + + for (long th : mxBean.getAllThreadIds()) + { + ThreadInfo ti = mxBean.getThreadInfo( th, Integer.MAX_VALUE ); + addStacktrace.invoke( StackTraceSnapshotBuilder_Instance, new ThreadInfo[] { ti }, System.nanoTime() ); + } + + Thread.sleep( 20 ); + } + + Object CPUResultsSnapshot_Instance = createSnapshot.invoke( StackTraceSnapshotBuilder_Instance, System.currentTimeMillis() ); + + Object LoadedSnapshot_Instance = LoadedSnapshot_Constructor.newInstance( CPUResultsSnapshot_Instance, + createCPUPreset.invoke( ProfilingSettingsPresets ), null, null ); + + FileOutputStream bout = new FileOutputStream( new File( "ae-latest-profile.nps" ) ); + DataOutputStream out = new DataOutputStream( bout ); + save.invoke( LoadedSnapshot_Instance, out ); + out.flush(); + bout.close(); + } + catch (Throwable t) + { + AELog.severe( "Error while profiling" ); + t.printStackTrace(); + profile = false; + return; + } + } + else + { + try + { + synchronized (lock) + { + lock.wait(); + } + } + catch (InterruptedException e) + { + + } + } + + } + + } +} \ No newline at end of file diff --git a/services/VersionChecker.java b/services/VersionChecker.java new file mode 100644 index 00000000..840ab0c5 --- /dev/null +++ b/services/VersionChecker.java @@ -0,0 +1,86 @@ +package appeng.services; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.minecraft.crash.CallableMinecraftVersion; +import appeng.core.Configuration; + +public class VersionChecker implements Runnable +{ + + public static VersionChecker instance = null; + + private long delay = 0; + + public VersionChecker() { + long now = (new Date()).getTime(); + delay = (1000 * 3600 * 5) - (now - Configuration.instance.latestTimeStamp); + if ( delay < 1 ) + delay = 1; + } + + @Override + public void run() + { + try + { + Thread.sleep( delay ); + } + catch (InterruptedException e) + { + } + + while (true) + { + Thread.yield(); + try + { + URL url = new URL( "http://ae-mod.info/releases/?latest" ); + + URLConnection yc = url.openConnection(); + yc.setRequestProperty( "User-Agent", "AE2/" + Configuration.VERSION + " (Channel:" + Configuration.CHANNEL + + ",Minecraft:" + ((new CallableMinecraftVersion( null )).minecraftVersion()) + ")" ); + + BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream() ) ); + + String Version = ""; + String inputLine; + + while ((inputLine = in.readLine()) != null) + Version += inputLine; + + in.close(); + + if ( Version.length() > 2 ) + { + Matcher m = Pattern.compile( "\"Version\":\"([^\"]+)\"" ).matcher( Version ); + m.find(); + Version = m.group( 1 ); + Configuration.instance.latestVersion = Version; + Configuration.instance.latestTimeStamp = (new Date()).getTime(); + Configuration.instance.save(); + } + + Thread.sleep( 1000 * 3600 * 4 ); + } + catch (Exception e) + { + try + { + Thread.sleep( 1000 * 3600 * 4 ); + } + catch (InterruptedException e1) + { + e1.printStackTrace(); + } + } + } + } + +} diff --git a/spatial/BiomeGenStorage.java b/spatial/BiomeGenStorage.java new file mode 100644 index 00000000..449e64e1 --- /dev/null +++ b/spatial/BiomeGenStorage.java @@ -0,0 +1,25 @@ +package appeng.spatial; + +import net.minecraft.world.biome.BiomeGenBase; + +public class BiomeGenStorage extends BiomeGenBase +{ + + public BiomeGenStorage(int id) { + super( id ); + this.setBiomeName( "Storage Cell" ); + + this.setDisableRain(); + this.temperature = -100; + + this.theBiomeDecorator.treesPerChunk = 0; + this.theBiomeDecorator.flowersPerChunk = 0; + this.theBiomeDecorator.grassPerChunk = 0; + + this.spawnableMonsterList.clear(); + this.spawnableCreatureList.clear(); + this.spawnableWaterCreatureList.clear(); + this.spawnableCaveCreatureList.clear(); + } + +} diff --git a/spatial/CachedPlane.java b/spatial/CachedPlane.java new file mode 100644 index 00000000..48dd3c86 --- /dev/null +++ b/spatial/CachedPlane.java @@ -0,0 +1,400 @@ +package appeng.spatial; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; + +import net.minecraft.block.Block; +import net.minecraft.network.packet.Packet51MapChunk; +import net.minecraft.server.management.PlayerInstance; +import net.minecraft.server.management.PlayerManager; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkPosition; +import net.minecraft.world.NextTickListEntry; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.movable.IMovableHandler; +import appeng.api.movable.IMovableRegistry; +import appeng.api.util.WorldCoord; +import appeng.core.AELog; +import cpw.mods.fml.common.FMLLog; + +public class CachedPlane +{ + + class Column + { + + private final int x; + private final int z; + private final Chunk c; + private final int ch[] = { 0, 0, 0 }; + private List skipThese = null; + + private ExtendedBlockStorage[] storage; + + public Column(Chunk _c, int _x, int _z, int cy, int y_clen) { + x = _x; + z = _z; + c = _c; + storage = c.getBlockStorageArray(); + + // make sure storage exists before hand... + for (int ay = 0; ay < y_clen; ay++) + { + int by = (ay + cy); + ExtendedBlockStorage extendedblockstorage = storage[by]; + if ( extendedblockstorage == null ) + extendedblockstorage = storage[by] = new ExtendedBlockStorage( by << 4, !c.worldObj.provider.hasNoSky ); + } + } + + public void setBlockIDWithMetadata(int y, int[] blk) + { + ExtendedBlockStorage extendedblockstorage = storage[y >> 4]; + extendedblockstorage.setExtBlockID( x, y & 15, z, blk[0] ); + extendedblockstorage.setExtBlockMetadata( x, y & 15, z, blk[1] ); + extendedblockstorage.setExtBlocklightValue( x, y & 15, z, blk[2] ); + } + + public int[] getDetails(int y) + { + ExtendedBlockStorage extendedblockstorage = storage[y >> 4]; + ch[0] = extendedblockstorage.getExtBlockID( x, y & 15, z ); + ch[1] = extendedblockstorage.getExtBlockMetadata( x, y & 15, z ); + ch[2] = extendedblockstorage.getExtBlocklightValue( x, y & 15, z ); + return ch; + } + + public boolean dontSkip(int y) + { + return skipThese == null ? true : !skipThese.contains( y ); + } + + public void setSkip(int yCoord) + { + if ( skipThese == null ) + skipThese = new LinkedList(); + skipThese.add( yCoord ); + } + + }; + + int verticalBits; + + int x_size; + int z_size; + + int cx_size; + int cz_size; + + int x_offset; + int y_offset; + int z_offset; + + int y_size; + + Chunk myChunks[][]; + Column myColumns[][]; + + LinkedList tiles = new LinkedList(); + LinkedList ticks = new LinkedList(); + + World wrld; + + LinkedList updates = new LinkedList(); + + public CachedPlane(World w, int minx, int miny, int minz, int maxx, int maxy, int maxz) { + + wrld = w; + + x_size = maxx - minx + 1; + y_size = maxy - miny + 1; + z_size = maxz - minz + 1; + + x_offset = minx; + y_offset = miny; + z_offset = minz; + + int minCX = minx >> 4; + int minCY = miny >> 4; + int minCZ = minz >> 4; + int maxCX = maxx >> 4; + int maxCY = maxy >> 4; + int maxCZ = maxz >> 4; + + cx_size = maxCX - minCX + 1; + int cy_size = maxCY - minCY + 1; + cz_size = maxCZ - minCZ + 1; + + myChunks = new Chunk[cx_size][cz_size]; + myColumns = new Column[x_size][z_size]; + + verticalBits = 0; + for (int cy = 0; cy < cy_size; cy++) + { + verticalBits |= 1 << (minCY + cy); + } + + for (int x = 0; x < x_size; x++) + for (int z = 0; z < z_size; z++) + { + myColumns[x][z] = new Column( w.getChunkFromChunkCoords( (minx + x) >> 4, (minz + z) >> 4 ), (minx + x) & 0xF, (minz + z) & 0xF, minCY, cy_size ); + } + + IMovableRegistry mr = AEApi.instance().registries().moveable(); + + for (int cx = 0; cx < cx_size; cx++) + for (int cz = 0; cz < cz_size; cz++) + { + LinkedList> rwarTiles = new LinkedList(); + LinkedList deadTiles = new LinkedList(); + + Chunk c = w.getChunkFromChunkCoords( minCX + cx, minCZ + cz ); + myChunks[cx][cz] = c; + + rwarTiles.addAll( ((HashMap) c.chunkTileEntityMap).entrySet() ); + for (Entry tx : rwarTiles) + { + ChunkPosition cp = tx.getKey(); + TileEntity te = tx.getValue(); + if ( te.xCoord >= minx && te.xCoord <= maxx && te.yCoord >= miny && te.yCoord <= maxy && te.zCoord >= minz && te.zCoord <= maxz ) + { + if ( mr.askToMove( te ) ) + { + tiles.add( te ); + deadTiles.add( cp ); + } + else + { + int[] details = myColumns[te.xCoord - minx][te.zCoord - minz].getDetails( te.yCoord ); + Block blk = Block.blocksList[details[0]]; + + // don't skip air, juset let the code replace it... + if ( blk != null && blk.isAirBlock( c.worldObj, te.xCoord, te.yCoord, te.zCoord ) + && blk.isBlockReplaceable( c.worldObj, te.xCoord, te.yCoord, te.zCoord ) ) + { + c.worldObj.setBlock( te.xCoord, te.yCoord, te.zCoord, 0 ); + c.worldObj.notifyBlocksOfNeighborChange( te.xCoord, te.yCoord, te.zCoord, 0 ); + } + else + myColumns[te.xCoord - minx][te.zCoord - minz].setSkip( te.yCoord ); + } + } + } + + for (ChunkPosition cp : deadTiles) + { + c.chunkTileEntityMap.remove( cp ); + } + + long k = wrld.getTotalWorldTime(); + List list = wrld.getPendingBlockUpdates( c, false ); + if ( list != null ) + { + for (Object o : list) + { + NextTickListEntry ntle = (NextTickListEntry) o; + if ( ntle.xCoord >= minx && ntle.xCoord <= maxx && ntle.yCoord >= miny && ntle.yCoord <= maxy && ntle.zCoord >= minz && ntle.zCoord <= maxz ) + { + NextTickListEntry newEntry = new NextTickListEntry( ntle.xCoord, ntle.yCoord, ntle.zCoord, ntle.blockID ); + newEntry.scheduledTime = ntle.scheduledTime - k; + ticks.add( newEntry ); + } + } + } + + } + + for (TileEntity te : tiles) + { + try + { + wrld.loadedTileEntityList.remove( te ); + } + catch (Exception _) + { + _.printStackTrace(); + } + } + } + + private IMovableHandler getHandler(TileEntity te) + { + IMovableRegistry mr = AEApi.instance().registries().moveable(); + return mr.getHandler( te ); + } + + void Swap(CachedPlane dst) + { + IMovableRegistry mr = AEApi.instance().registries().moveable(); + + if ( dst.x_size == x_size && dst.y_size == y_size && dst.z_size == z_size ) + { + AELog.info( "Block Copy Scale: " + x_size + ", " + y_size + ", " + z_size ); + + long startTime = System.nanoTime(); + + for (int x = 0; x < x_size; x++) + { + for (int z = 0; z < z_size; z++) + { + Column a = myColumns[x][z]; + Column b = dst.myColumns[x][z]; + + for (int y = 0; y < y_size; y++) + { + int src_y = y + y_offset; + int dst_y = y + dst.y_offset; + + if ( a.dontSkip( src_y ) && b.dontSkip( dst_y ) ) + { + int[] aD = a.getDetails( src_y ); + int[] bD = b.getDetails( dst_y ); + + a.setBlockIDWithMetadata( src_y, bD ); + b.setBlockIDWithMetadata( dst_y, aD ); + } + else + { + markForUpdate( x + x_offset, src_y, z + z_offset ); + dst.markForUpdate( x + dst.x_offset, dst_y, z + dst.z_offset ); + } + } + + } + } + + long endTime = System.nanoTime(); + long duration = endTime - startTime; + AELog.info( "Block Copy Time: " + duration ); + + for (TileEntity te : tiles) + { + dst.addTile( te.xCoord - x_offset, te.yCoord - y_offset, te.zCoord - z_offset, te, this, mr ); + } + + for (TileEntity te : dst.tiles) + { + addTile( te.xCoord - dst.x_offset, te.yCoord - dst.y_offset, te.zCoord - dst.z_offset, te, dst, mr ); + } + + for (NextTickListEntry ntle : ticks) + { + dst.addTick( ntle.xCoord - x_offset, ntle.yCoord - y_offset, ntle.zCoord - z_offset, ntle ); + } + + for (NextTickListEntry ntle : dst.ticks) + { + addTick( ntle.xCoord - dst.x_offset, ntle.yCoord - dst.y_offset, ntle.zCoord - dst.z_offset, ntle ); + } + + startTime = System.nanoTime(); + updateChunks(); + dst.updateChunks(); + endTime = System.nanoTime(); + + duration = endTime - startTime; + AELog.info( "Update Time: " + duration ); + } + } + + private void markForUpdate(int src_x, int src_y, int src_z) + { + updates.add( new WorldCoord( src_x, src_y, src_z ) ); + for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) + updates.add( new WorldCoord( src_x + d.offsetX, src_y + d.offsetY, src_z + d.offsetZ ) ); + } + + private void addTick(int x, int y, int z, NextTickListEntry ntle) + { + wrld.scheduleBlockUpdate( x + x_offset, y + y_offset, z + z_offset, ntle.blockID, (int) ntle.scheduledTime ); + } + + private void addTile(int x, int y, int z, TileEntity te, CachedPlane alernateDest, IMovableRegistry mr) + { + try + { + Column c = myColumns[x][z]; + + if ( c.dontSkip( y + y_offset ) || alernateDest == null ) + { + IMovableHandler handler = getHandler( te ); + + try + { + handler.moveTile( te, wrld, x + x_offset, y + y_offset, z + z_offset ); + } + catch (Throwable _) + { + _.printStackTrace(); + + // attempt recovery... + te.worldObj = wrld; + te.xCoord = x; + te.yCoord = y; + te.zCoord = z; + + c.c.setChunkBlockTileEntity( c.x, y + y, c.z, te ); + + if ( c.c.isChunkLoaded ) + { + wrld.addTileEntity( te ); + wrld.markBlockForUpdate( x, y, z ); + } + } + + mr.doneMoving( te ); + } + else + { + alernateDest.addTile( x, y, z, te, null, mr ); + } + } + catch (Throwable _) + { + _.printStackTrace(); + } + } + + private void updateChunks() + { + + // update shit.. + for (int x = 0; x < cx_size; x++) + for (int z = 0; z < cz_size; z++) + { + Chunk c = myChunks[x][z]; + for (Method m : c.getClass().getMethods()) + { + FMLLog.severe( "Chunk." + m.getName() ); + } + + c.resetRelightChecks(); + c.generateSkylightMap(); + c.isModified = true; + } + + // send shit... + for (int x = 0; x < cx_size; x++) + for (int z = 0; z < cz_size; z++) + { + Chunk c = myChunks[x][z]; + + WorldServer ws = (WorldServer) c.worldObj; + PlayerManager pm = ws.getPlayerManager(); + PlayerInstance playerinstance = pm.getOrCreateChunkWatcher( c.xPosition, c.zPosition, false ); + + if ( playerinstance != null ) + playerinstance.sendToAllPlayersWatchingChunk( new Packet51MapChunk( c, false, verticalBits ) ); + } + + } + +} diff --git a/spatial/DefaultSpatialHandler.java b/spatial/DefaultSpatialHandler.java new file mode 100644 index 00000000..b7ec5bb7 --- /dev/null +++ b/spatial/DefaultSpatialHandler.java @@ -0,0 +1,42 @@ +package appeng.spatial; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import appeng.api.movable.IMovableHandler; + +public class DefaultSpatialHandler implements IMovableHandler +{ + + @Override + public void moveTile(TileEntity te, World w, int x, int y, int z) + { + + te.worldObj = w; + te.xCoord = x; + te.yCoord = y; + te.zCoord = z; + + Chunk c = w.getChunkFromBlockCoords( x, z ); + c.setChunkBlockTileEntity( x & 0xF, y, z & 0xF, te ); + + if ( c.isChunkLoaded ) + { + w.addTileEntity( te ); + w.markBlockForUpdate( x, y, z ); + } + } + + /** + * never called for the default. + * + * @param tile + * @return + */ + @Override + public boolean canHandle(Class myClass, TileEntity tile) + { + return true; + } + +} diff --git a/spatial/ISpatialVisitor.java b/spatial/ISpatialVisitor.java new file mode 100644 index 00000000..84fd7139 --- /dev/null +++ b/spatial/ISpatialVisitor.java @@ -0,0 +1,8 @@ +package appeng.spatial; + +public interface ISpatialVisitor +{ + + void visit(int x, int y, int z); + +} diff --git a/spatial/StorageChunkProvider.java b/spatial/StorageChunkProvider.java new file mode 100644 index 00000000..c9a5b367 --- /dev/null +++ b/spatial/StorageChunkProvider.java @@ -0,0 +1,64 @@ +package appeng.spatial; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.world.ChunkPosition; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderGenerate; + +public class StorageChunkProvider extends ChunkProviderGenerate implements IChunkProvider +{ + + World w; + + public StorageChunkProvider(World wrd, long i) { + super( wrd, i, false ); + this.w = wrd; + } + + @Override + public boolean unloadQueuedChunks() + { + return true; + } + + @Override + public Chunk provideChunk(int x, int z) + { + + byte[] data = new byte[32768]; + + Chunk chunk = new Chunk( w, data, x, z ); + + if ( !chunk.isTerrainPopulated ) + { + chunk.isTerrainPopulated = true; + chunk.resetRelightChecks(); + } + + return chunk; + } + + @Override + public void populate(IChunkProvider par1iChunkProvider, int par2, int par3) + { + + } + + @Override + public List getPossibleCreatures(EnumCreatureType a, int b, int c, int d) + { + return new ArrayList(); + } + + @Override + public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) + { + return null; + } + +} diff --git a/spatial/StorageHelper.java b/spatial/StorageHelper.java new file mode 100644 index 00000000..b1240e29 --- /dev/null +++ b/spatial/StorageHelper.java @@ -0,0 +1,302 @@ +package appeng.spatial; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.world.Teleporter; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import appeng.api.AEApi; +import appeng.api.util.WorldCoord; +import appeng.block.solids.BlockMatrixFrame; + +public class StorageHelper +{ + + private static StorageHelper instance; + + public static StorageHelper getInstance() + { + if ( instance == null ) + instance = new StorageHelper(); + return instance; + } + + class triggerUpdates implements ISpatialVisitor + { + + World dst; + + public triggerUpdates(World dst2) { + dst = dst2; + } + + @Override + public void visit(int x, int y, int z) + { + int blk = dst.getBlockId( x, y, z ); + if ( blk > 0 ) + Block.blocksList[blk].onNeighborBlockChange( dst, x, y, z, 0 ); + } + }; + + class WrapInMatrixFrame implements ISpatialVisitor + { + + World dst; + int blkID, Meta; + + public WrapInMatrixFrame(int blockID, int metaData, World dst2) { + dst = dst2; + blkID = blockID; + Meta = metaData; + } + + @Override + public void visit(int x, int y, int z) + { + dst.setBlock( x, y, z, blkID, Meta, 3 ); + } + }; + + class TelDestination + { + + TelDestination(World _dim, AxisAlignedBB srcBox, double _x, double _y, double _z) { + dim = _dim; + x = Math.min( srcBox.maxX - 0.5, Math.max( srcBox.minX + 0.5, _x ) ); + y = Math.min( srcBox.maxY - 0.5, Math.max( srcBox.minY + 0.5, _y ) ); + z = Math.min( srcBox.maxZ - 0.5, Math.max( srcBox.minZ + 0.5, _z ) ); + } + + final World dim; + final double x; + final double y; + final double z; + }; + + class METeleporter extends Teleporter + { + + TelDestination dest; + + public METeleporter(WorldServer par1WorldServer, TelDestination d) { + super( par1WorldServer ); + dest = d; + } + + @Override + public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) + { + par1Entity.setLocationAndAngles( dest.x, dest.y, dest.z, par1Entity.rotationYaw, 0.0F ); + par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D; + } + + @Override + public boolean makePortal(Entity par1Entity) + { + return false; + } + + @Override + public boolean placeInExistingPortal(Entity par1Entity, double par2, double par4, double par6, float par8) + { + return false; + } + + @Override + public void removeStalePortalLocations(long par1) + { + + } + + }; + + /** + * Mostly from dimentional doors.. which mostly got it form X-Comp. + * + * @param world + * @param entity + * @param link + * @return + */ + public Entity teleportEntity(Entity entity, TelDestination link) + { + WorldServer oldWorld, newWorld; + EntityPlayerMP player; + + try + { + oldWorld = (WorldServer) entity.worldObj; + newWorld = (WorldServer) link.dim; + player = (entity instanceof EntityPlayerMP) ? (EntityPlayerMP) entity : null; + } + catch (Throwable e) + { + return entity; + } + + if ( oldWorld == null ) + return entity; + if ( newWorld == null ) + return entity; + + // Is something riding? Handle it first. + if ( entity.riddenByEntity != null ) + { + return teleportEntity( entity.riddenByEntity, link ); + } + // Are we riding something? Dismount and tell the mount to go first. + Entity cart = entity.ridingEntity; + if ( cart != null ) + { + entity.mountEntity( null ); + cart = teleportEntity( cart, link ); + // We keep track of both so we can remount them on the other side. + } + + boolean difDest = newWorld != oldWorld; + if ( difDest ) + { + if ( player != null ) + { + player.mcServer.getConfigurationManager().transferPlayerToDimension( player, link.dim.provider.dimensionId, new METeleporter( newWorld, link ) ); + } + else + { + int entX = entity.chunkCoordX; + int entZ = entity.chunkCoordZ; + if ( (entity.addedToChunk) && (oldWorld.getChunkProvider().chunkExists( entX, entZ )) ) + { + oldWorld.getChunkFromChunkCoords( entX, entZ ).removeEntity( entity ); + oldWorld.getChunkFromChunkCoords( entX, entZ ).isModified = true; + } + + oldWorld.onEntityRemoved( entity ); + + if ( player == null ) // Are we NOT working with a player? + { + NBTTagCompound entityNBT = new NBTTagCompound(); + entity.posX = link.x; + entity.posY = link.y; + entity.posZ = link.z; + entity.prevPosX = link.x; + entity.prevPosY = link.y; + entity.prevPosZ = link.z; + entity.isDead = false; + entity.writeToNBTOptional( entityNBT ); + entity.isDead = true; + entity = EntityList.createEntityFromNBT( entityNBT, newWorld ); + } + + if ( entity == null ) + return entity; + + newWorld.spawnEntityInWorld( entity ); + entity.setWorld( newWorld ); + } + } + + entity.worldObj.updateEntityWithOptionalForce( entity, false ); + + if ( cart != null ) + { + if ( player != null ) + entity.worldObj.updateEntityWithOptionalForce( entity, true ); + + entity.mountEntity( cart ); + } + + if ( player != null ) + { + WorldServer.class.cast( newWorld ).getChunkProvider().loadChunk( MathHelper.floor_double( entity.posX ) >> 4, MathHelper.floor_double( entity.posZ ) >> 4 ); + } + + return entity; + } + + public void transverseEdges(int minx, int miny, int minz, int maxx, int maxy, int maxz, ISpatialVisitor obj) + { + for (int y = miny; y < maxy; y++) + for (int z = minz; z < maxz; z++) + { + obj.visit( minx, y, z ); + obj.visit( maxx, y, z ); + } + + for (int x = minx; x < maxx; x++) + for (int z = minz; z < maxz; z++) + { + obj.visit( x, miny, z ); + obj.visit( x, maxy, z ); + } + + for (int x = minx; x < maxx; x++) + for (int y = miny; y < maxy; y++) + { + obj.visit( x, y, minz ); + obj.visit( x, y, maxz ); + } + + } + + public void swapRegions(World src /** over world **/ + , World dst /** storage cell **/ + , int x, int y, int z, int i, int j, int k, int scaleX, int scaleY, int scaleZ) + { + BlockMatrixFrame blkMF = (BlockMatrixFrame) AEApi.instance().blocks().blockMatrixFrame.block(); + + transverseEdges( i - 1, j - 1, k - 1, i + scaleX + 1, j + scaleY + 1, k + scaleZ + 1, new WrapInMatrixFrame( blkMF.blockID, 0, dst ) ); + + AxisAlignedBB srcBox = AxisAlignedBB.getBoundingBox( x, y, z, x + scaleX + 1, y + scaleY + 1, z + scaleZ + 1 ); + + AxisAlignedBB dstBox = AxisAlignedBB.getBoundingBox( i, j, k, i + scaleX + 1, j + scaleY + 1, k + scaleZ + 1 ); + + CachedPlane cDst = new CachedPlane( dst, i, j, k, i + scaleX, j + scaleY, k + scaleZ ); + CachedPlane cSrc = new CachedPlane( src, x, y, z, x + scaleX, y + scaleY, z + scaleZ ); + + // do nearly all the work... swaps blocks, tiles, and block ticks + cSrc.Swap( cDst ); + + List srcE = src.getEntitiesWithinAABB( Entity.class, srcBox ); + List dstE = dst.getEntitiesWithinAABB( Entity.class, dstBox ); + + for (Entity e : dstE) + { + teleportEntity( e, new TelDestination( src, srcBox, e.posX - i + x, e.posY - j + y, e.posZ - k + z ) ); + } + + for (Entity e : srcE) + { + teleportEntity( e, new TelDestination( dst, dstBox, e.posX - x + i, e.posY - y + j, e.posZ - z + k ) ); + } + + for (WorldCoord wc : cDst.updates) + cDst.wrld.notifyBlockOfNeighborChange( wc.x, wc.y, wc.z, 0 ); + + for (WorldCoord wc : cSrc.updates) + cSrc.wrld.notifyBlockOfNeighborChange( wc.x, wc.y, wc.z, 0 ); + + transverseEdges( x - 1, y - 1, z - 1, x + scaleX + 1, y + scaleY + 1, z + scaleZ + 1, new triggerUpdates( src ) ); + transverseEdges( i - 1, j - 1, k - 1, i + scaleX + 1, j + scaleY + 1, k + scaleZ + 1, new triggerUpdates( dst ) ); + + transverseEdges( x, y, z, x + scaleX, y + scaleY, z + scaleZ, new triggerUpdates( src ) ); + transverseEdges( i, j, k, i + scaleX, j + scaleY, k + scaleZ, new triggerUpdates( dst ) ); + + /* + * IChunkProvider cp = dest.getChunkProvider(); if ( cp instanceof + * ChunkProviderServer ) { ChunkProviderServer srv = + * (ChunkProviderServer) cp; srv.unloadAllChunks(); } + * + * cp.unloadQueuedChunks(); + */ + + } + +} diff --git a/spatial/StorageWorldProvider.java b/spatial/StorageWorldProvider.java new file mode 100644 index 00000000..7b0184a6 --- /dev/null +++ b/spatial/StorageWorldProvider.java @@ -0,0 +1,112 @@ +package appeng.spatial; + +import net.minecraft.entity.Entity; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.util.Vec3; +import net.minecraft.world.WorldProvider; +import net.minecraft.world.biome.WorldChunkManagerHell; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; +import appeng.core.Registration; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class StorageWorldProvider extends WorldProvider +{ + + public StorageWorldProvider() { + this.hasNoSky = true; + } + + @Override + public ChunkCoordinates getSpawnPoint() + { + return new ChunkCoordinates( 0, 0, 0 ); + } + + @Override + public boolean canRespawnHere() + { + return false; + } + + @Override + protected void registerWorldChunkManager() + { + super.worldChunkMgr = new WorldChunkManagerHell( Registration.instance.storageBiome, 1, 1 ); + } + + @Override + public float getStarBrightness(float par1) + { + return 0; + } + + @Override + public boolean isSurfaceWorld() + { + return false; + } + + @Override + public boolean canDoLightning(Chunk chunk) + { + return false; + } + + @Override + public boolean isBlockHighHumidity(int x, int y, int z) + { + return false; + } + + @Override + public boolean isDaytime() + { + return false; + } + + @Override + public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) + { + return this.worldObj.getWorldVec3Pool().getVecFromPool( 0.0, 0.0, 0.0 ); + } + + @Override + public boolean doesXZShowFog(int par1, int par2) + { + return false; + } + + @Override + public float calculateCelestialAngle(long par1, float par3) + { + return 0; + } + + @Override + @SideOnly(Side.CLIENT) + public boolean isSkyColored() + { + return false; + } + + @Override + public Vec3 getFogColor(float par1, float par2) + { + return this.worldObj.getWorldVec3Pool().getVecFromPool( 0.0, 0.0, 0.0 ); + } + + @Override + public IChunkProvider createChunkGenerator() + { + return new StorageChunkProvider( worldObj, 0 ); + } + + @Override + public String getDimensionName() + { + return "Storage Cell"; + } + +} diff --git a/tile/AEBaseInvTile.java b/tile/AEBaseInvTile.java new file mode 100644 index 00000000..c300f123 --- /dev/null +++ b/tile/AEBaseInvTile.java @@ -0,0 +1,144 @@ +package appeng.tile; + +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.inventory.IAEAppEngInventory; +import appeng.tile.inventory.InvOperation; + +public abstract class AEBaseInvTile extends AEBaseTile implements ISidedInventory, IAEAppEngInventory +{ + + public AEBaseInvTile() { + addNewHandler( new AETileEventHandler( EnumSet.of( TileEventType.WORLD_NBT ) ) { + + @Override + public void readFromNBT(net.minecraft.nbt.NBTTagCompound data) + { + IInventory inv = getInternalInventory(); + NBTTagCompound opt = data.getCompoundTag( "inv" ); + for (int x = 0; x < inv.getSizeInventory(); x++) + { + NBTTagCompound item = opt.getCompoundTag( "item" + x ); + inv.setInventorySlotContents( x, ItemStack.loadItemStackFromNBT( item ) ); + } + } + + @Override + public void writeToNBT(net.minecraft.nbt.NBTTagCompound data) + { + IInventory inv = getInternalInventory(); + NBTTagCompound opt = new NBTTagCompound(); + for (int x = 0; x < inv.getSizeInventory(); x++) + { + NBTTagCompound item = new NBTTagCompound(); + ItemStack is = getStackInSlot( x ); + if ( is != null ) + is.writeToNBT( item ); + opt.setCompoundTag( "item" + x, item ); + } + data.setCompoundTag( "inv", opt ); + } + + } ); + } + + @Override + public int getSizeInventory() + { + return getInternalInventory().getSizeInventory(); + } + + @Override + public ItemStack getStackInSlot(int i) + { + return getInternalInventory().getStackInSlot( i ); + } + + @Override + public ItemStack decrStackSize(int i, int j) + { + return getInternalInventory().decrStackSize( i, j ); + } + + @Override + public ItemStack getStackInSlotOnClosing(int i) + { + return null; + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemstack) + { + getInternalInventory().setInventorySlotContents( i, itemstack ); + } + + @Override + public String getInvName() + { + return getClass().getSimpleName(); + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer p) + { + return this.worldObj.getBlockTileEntity( this.xCoord, this.yCoord, this.zCoord ) != this ? false : p.getDistanceSq( (double) this.xCoord + 0.5D, + (double) this.yCoord + 0.5D, (double) this.zCoord + 0.5D ) <= 32.0D; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean canInsertItem(int i, ItemStack itemstack, int j) + { + return isItemValidForSlot( i, itemstack ); + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return true; + } + + @Override + public abstract IInventory getInternalInventory(); + + @Override + public abstract void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added); + + @Override + public abstract int[] getAccessibleSlotsFromSide(int side); + +} diff --git a/tile/AEBaseTile.java b/tile/AEBaseTile.java new file mode 100644 index 00000000..b8f6a27f --- /dev/null +++ b/tile/AEBaseTile.java @@ -0,0 +1,310 @@ +package appeng.tile; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.Packet132TileEntityData; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.ICommonTile; +import appeng.api.util.IOrientable; +import appeng.core.AELog; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.util.SettingsFrom; + +public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile +{ + + private final EnumMap> handlers = new EnumMap>( TileEventType.class ); + + private ForgeDirection forward = ForgeDirection.UNKNOWN; + private ForgeDirection up = ForgeDirection.UNKNOWN; + + public boolean dropItems = true; + + /** + * isRedstonePowerd has already changed. + */ + public void onRedstoneEvent() + { + + } + + protected boolean hasHandlerFor(TileEventType type) + { + List list = handlers.get( type ); + return list != null; + } + + protected List getHandlerListFor(TileEventType type) + { + List list = handlers.get( type ); + + if ( list == null ) + handlers.put( type, list = new LinkedList() ); + + return list; + } + + protected void addNewHandler(AETileEventHandler handler) + { + EnumSet types = handler.getSubscribedEvents(); + + for (TileEventType type : types) + getHandlerListFor( type ).add( handler ); + } + + @Override + final public boolean canUpdate() + { + return hasHandlerFor( TileEventType.TICK ); + } + + @Override + final public void updateEntity() + { + for (AETileEventHandler h : getHandlerListFor( TileEventType.TICK )) + h.Tick(); + } + + @Override + final public void writeToNBT(NBTTagCompound data) + { + super.writeToNBT( data ); + + if ( canBeRotated() ) + { + data.setString( "orientation_forward", forward.name() ); + data.setString( "orientation_up", up.name() ); + } + + for (AETileEventHandler h : getHandlerListFor( TileEventType.WORLD_NBT )) + h.writeToNBT( data ); + } + + @Override + final public void readFromNBT(NBTTagCompound data) + { + super.readFromNBT( data ); + + try + { + if ( canBeRotated() ) + { + forward = ForgeDirection.valueOf( data.getString( "orientation_forward" ) ); + up = ForgeDirection.valueOf( data.getString( "orientation_up" ) ); + } + } + catch (IllegalArgumentException iae) + { + } + + for (AETileEventHandler h : getHandlerListFor( TileEventType.WORLD_NBT )) + { + h.readFromNBT( data ); + } + } + + final public void writeToStream(DataOutputStream data) + { + try + { + if ( canBeRotated() ) + { + byte orientation = (byte) ((up.ordinal() << 3) | forward.ordinal()); + data.writeByte( orientation ); + } + + for (AETileEventHandler h : getHandlerListFor( TileEventType.NETWORK )) + h.writeToStream( data ); + } + catch (Throwable t) + { + t.printStackTrace(); + } + } + + final public boolean readfromStream(DataInputStream data) + { + boolean output = false; + + try + { + + if ( canBeRotated() ) + { + ForgeDirection old_Forward = forward; + ForgeDirection old_Up = up; + + byte orientation = data.readByte(); + forward = ForgeDirection.getOrientation( orientation & 0x7 ); + up = ForgeDirection.getOrientation( orientation >> 3 ); + + output = !forward.equals( old_Forward ) || !up.equals( old_Up ); + } + + for (AETileEventHandler h : getHandlerListFor( TileEventType.NETWORK )) + if ( h.readFromStream( data ) ) + output = true; + } + catch (Throwable t) + { + t.printStackTrace(); + } + + return output; + } + + /** + * By default all blocks can have orientation, this handles saving, and loading, as well as synchronization. + * + * @return + */ + @Override + public boolean canBeRotated() + { + return true; + } + + @Override + public ForgeDirection getForward() + { + return forward; + } + + @Override + public ForgeDirection getUp() + { + return up; + } + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + forward = inForward; + up = inUp; + markForUpdate(); + worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, 0 ); + } + + public void onPlacement(ItemStack stack, EntityPlayer player, int side) + { + if ( stack.hasTagCompound() ) + { + uploadSettings( SettingsFrom.DISMANTLE_ITEM, stack.getTagCompound() ); + } + } + + @Override + public Packet getDescriptionPacket() + { + NBTTagCompound data = new NBTTagCompound(); + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream stream = new DataOutputStream( bytes ); + + try + { + writeToStream( stream ); + if ( bytes.size() == 0 ) + return null; + } + catch (Throwable t) + { + AELog.error( t ); + } + + data.setByteArray( "X", bytes.toByteArray() ); + return new Packet132TileEntityData( xCoord, yCoord, zCoord, 64, data ); + } + + @Override + public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt) + { + if ( pkt.actionType == 64 ) + { + DataInputStream stream = new DataInputStream( new ByteArrayInputStream( pkt.data.getByteArray( "X" ) ) ); + if ( readfromStream( stream ) ) + markForUpdate(); + } + } + + public void markForUpdate() + { + if ( worldObj != null ) + worldObj.markBlockForUpdate( xCoord, yCoord, zCoord ); + } + + /** + * returns the contents of the tile entity, into the world, defaults to dropping everything in the inventory. + * + * @param w + * @param x + * @param y + * @param z + * @param drops + */ + @Override + public void getDrops(World w, int x, int y, int z, ArrayList drops) + { + if ( this instanceof IInventory ) + { + IInventory inv = (IInventory) this; + + for (int l = 0; l < inv.getSizeInventory(); l++) + { + ItemStack is = inv.getStackInSlot( l ); + + if ( is != null ) + { + drops.add( is ); + inv.setInventorySlotContents( l, (ItemStack) null ); + } + } + } + + } + + public void onReady() + { + + } + + /** + * depending on the from, diffrent settings will be accepted, don't call this with null + * + * @param from + * @param compound + */ + public void uploadSettings(SettingsFrom from, NBTTagCompound compound) + { + + } + + /** + * null means nothing to store... + * + * @param from + * @return + */ + public NBTTagCompound downloadSettings(SettingsFrom from) + { + return null; + } + +} diff --git a/tile/events/AETileEventHandler.java b/tile/events/AETileEventHandler.java new file mode 100644 index 00000000..cd59d74f --- /dev/null +++ b/tile/events/AETileEventHandler.java @@ -0,0 +1,60 @@ +package appeng.tile.events; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.nbt.NBTTagCompound; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public abstract class AETileEventHandler +{ + + final EnumSet supportedEvents; + + public AETileEventHandler(EnumSet events) { + supportedEvents = events; + } + + public EnumSet getSubscribedEvents() + { + return supportedEvents; + } + + // TICK + public void Tick() + { + } + + // WORLD_NBT + public void writeToNBT(NBTTagCompound data) + { + } + + // WORLD NBT + public void readFromNBT(NBTTagCompound data) + { + } + + // NETWORK + public void writeToStream(DataOutputStream data) throws IOException + { + } + + // NETWORK + /** + * returning true from this method, will update the block's render + * + * @param data + * @return + * @throws IOException + */ + @SideOnly(Side.CLIENT) + public boolean readFromStream(DataInputStream data) throws IOException + { + return false; + } + +} diff --git a/tile/events/TileEventType.java b/tile/events/TileEventType.java new file mode 100644 index 00000000..d78a8509 --- /dev/null +++ b/tile/events/TileEventType.java @@ -0,0 +1,6 @@ +package appeng.tile.events; + +public enum TileEventType +{ + TICK, WORLD_NBT, NETWORK +} diff --git a/tile/grid/AENetworkInvTile.java b/tile/grid/AENetworkInvTile.java new file mode 100644 index 00000000..95ac7e7d --- /dev/null +++ b/tile/grid/AENetworkInvTile.java @@ -0,0 +1,54 @@ +package appeng.tile.grid; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.IGridProxyable; +import appeng.tile.AEBaseInvTile; + +public abstract class AENetworkInvTile extends AEBaseInvTile implements IGridHost, IGridProxyable +{ + + protected AENetworkProxy gridProxy = new AENetworkProxy( this, "proxy", true ); + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return gridProxy.getNode(); + } + + @Override + public void onReady() + { + super.onReady(); + gridProxy.onReady(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + gridProxy.onChunkUnload(); + } + + @Override + public void validate() + { + super.validate(); + gridProxy.validate(); + } + + @Override + public void invalidate() + { + super.invalidate(); + gridProxy.invalidate(); + } + + @Override + public void gridChanged() + { + + } +} diff --git a/tile/grid/AENetworkPowerTile.java b/tile/grid/AENetworkPowerTile.java new file mode 100644 index 00000000..a649cd57 --- /dev/null +++ b/tile/grid/AENetworkPowerTile.java @@ -0,0 +1,68 @@ +package appeng.tile.grid; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.IGridProxyable; +import appeng.tile.powersink.AEBasePoweredTile; + +public abstract class AENetworkPowerTile extends AEBasePoweredTile implements IGridHost, IGridProxyable +{ + + protected AENetworkProxy gridProxy = new AENetworkProxy( this, "proxy", true ); + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return gridProxy.getNode(); + } + + @Override + public void onReady() + { + super.onReady(); + gridProxy.onReady(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + gridProxy.onChunkUnload(); + } + + @Override + public void validate() + { + super.validate(); + gridProxy.validate(); + } + + @Override + public void invalidate() + { + super.invalidate(); + gridProxy.invalidate(); + } + + @Override + public void gridChanged() + { + + } +} diff --git a/tile/grid/AENetworkTile.java b/tile/grid/AENetworkTile.java new file mode 100644 index 00000000..d50586ea --- /dev/null +++ b/tile/grid/AENetworkTile.java @@ -0,0 +1,73 @@ +package appeng.tile.grid; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.IGridProxyable; +import appeng.tile.AEBaseTile; + +public class AENetworkTile extends AEBaseTile implements IGridHost, IGridProxyable +{ + + final protected AENetworkProxy gridProxy = createProxy(); + + protected AENetworkProxy createProxy() + { + return new AENetworkProxy( this, "proxy", true ); + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return gridProxy.getNode(); + } + + @Override + public void onReady() + { + super.onReady(); + gridProxy.onReady(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + gridProxy.onChunkUnload(); + } + + @Override + public void validate() + { + super.validate(); + gridProxy.validate(); + } + + @Override + public void invalidate() + { + super.invalidate(); + gridProxy.invalidate(); + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public void gridChanged() + { + + } +} diff --git a/tile/grindstone/TileCrank.java b/tile/grindstone/TileCrank.java new file mode 100644 index 00000000..537b4f42 --- /dev/null +++ b/tile/grindstone/TileCrank.java @@ -0,0 +1,133 @@ +package appeng.tile.grindstone; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.ICrankable; +import appeng.helpers.ICustomCollision; +import appeng.tile.AEBaseTile; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.util.Platform; + +public class TileCrank extends AEBaseTile implements ICustomCollision +{ + + final int ticksPerRoation = 18; + + // sided values.. + public float visibleRotation = 0; + public int charge = 0; + + public int hits = 0; + public int rotation = 0; + + public TileCrank() { + addNewHandler( new AETileEventHandler( EnumSet.of( TileEventType.NETWORK, TileEventType.TICK ) ) { + + @Override + public void Tick() + { + if ( rotation > 0 ) + { + visibleRotation -= 360 / (ticksPerRoation); + charge++; + if ( charge >= ticksPerRoation ) + { + charge -= ticksPerRoation; + ICrankable g = getGrinder(); + if ( g != null ) + g.applyTurn(); + } + + rotation--; + } + } + + @Override + public boolean readFromStream(java.io.DataInputStream data) throws java.io.IOException + { + rotation = data.readInt(); + return false; + } + + @Override + public void writeToStream(java.io.DataOutputStream data) throws java.io.IOException + { + data.writeInt( rotation ); + } + + } ); + } + + public ICrankable getGrinder() + { + if ( Platform.isClient() ) + return null; + + ForgeDirection grinder = getUp().getOpposite(); + TileEntity te = worldObj.getBlockTileEntity( xCoord + grinder.offsetX, yCoord + grinder.offsetY, zCoord + grinder.offsetZ ); + if ( te instanceof ICrankable ) + return (ICrankable) te; + return null; + } + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + super.setOrientation( inForward, inUp ); + getBlockType().onNeighborBlockChange( worldObj, xCoord, yCoord, zCoord, 0 ); + } + + public void power() + { + if ( Platform.isClient() ) + return; + + if ( rotation < 3 ) + { + ICrankable g = getGrinder(); + if ( g != null ) + { + if ( g.canTurn() ) + { + hits = 0; + rotation += ticksPerRoation; + this.markForUpdate(); + } + else + { + hits++; + if ( hits > 10 ) + worldObj.destroyBlock( xCoord, yCoord, zCoord, false ); + } + } + } + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + double xOff = -0.15 * getUp().offsetX; + double yOff = -0.15 * getUp().offsetY; + double zOff = -0.15 * getUp().offsetZ; + return Arrays + .asList( new AxisAlignedBB[] { AxisAlignedBB.getBoundingBox( xOff + 0.15, yOff + 0.15, zOff + 0.15, xOff + 0.85, yOff + 0.85, zOff + 0.85 ) } ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + double xOff = -0.15 * getUp().offsetX; + double yOff = -0.15 * getUp().offsetY; + double zOff = -0.15 * getUp().offsetZ; + out.add( AxisAlignedBB.getAABBPool().getAABB( xOff + (double) 0.15, yOff + (double) 0.15, zOff + (double) 0.15,// ahh + xOff + (double) 0.85, yOff + (double) 0.85, zOff + (double) 0.85 ) ); + } +} diff --git a/tile/grindstone/TileGrinder.java b/tile/grindstone/TileGrinder.java new file mode 100644 index 00000000..c4eda8ee --- /dev/null +++ b/tile/grindstone/TileGrinder.java @@ -0,0 +1,154 @@ +package appeng.tile.grindstone; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.features.IGrinderEntry; +import appeng.api.implementations.ICrankable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.WorldCoord; +import appeng.me.storage.MEIInventoryWrapper; +import appeng.tile.AEBaseInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.inv.WrapperInventoryRange; +import appeng.util.item.ItemList; + +public class TileGrinder extends AEBaseInvTile implements ICrankable +{ + + int points; + + final int inputs[] = new int[] { 0, 1, 2 }; + final int sides[] = new int[] { 0, 1, 2, 3, 4, 5 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 7 ); + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + super.setOrientation( inForward, inUp ); + getBlockType().onNeighborBlockChange( worldObj, xCoord, yCoord, zCoord, 0 ); + } + + private void addItem(InventoryAdaptor sia, ItemStack output) + { + ItemStack notAdded = sia.addItems( output ); + if ( notAdded != null ) + { + WorldCoord wc = new WorldCoord( xCoord, yCoord, zCoord ); + + wc.add( getForward(), 1 ); + + List out = new ArrayList(); + out.add( notAdded ); + + Platform.spawnDrops( worldObj, wc.x, wc.y, wc.z, out ); + } + } + + @Override + public boolean canInsertItem(int i, ItemStack itemstack, int j) + { + if ( AEApi.instance().registries().grinder().getRecipeForInput( itemstack ) == null ) + return false; + + return i >= 0 && i <= 2; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return i >= 3 && i <= 5; + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + @Override + public boolean canTurn() + { + if ( Platform.isClient() ) + return false; + + if ( null == this.getStackInSlot( 6 ) ) // Add if there isn't one... + { + IMEInventory input = new MEIInventoryWrapper( new WrapperInventoryRange( this, inputs, true ), null ); + for (IAEItemStack i : input.getAvailableItems( new ItemList() )) + { + IGrinderEntry r = AEApi.instance().registries().grinder().getRecipeForInput( i.getItemStack() ); + if ( r != null ) + { + if ( i.getStackSize() >= r.getInput().stackSize ) + { + i = i.copy(); + i.setStackSize( r.getInput().stackSize ); + IAEItemStack ais = input.extractItems( (IAEItemStack) i, Actionable.MODULATE ); + if ( ais != null ) + this.setInventorySlotContents( 6, ais.getItemStack() ); + return true; + } + } + } + return false; + } + return true; + } + + @Override + public void applyTurn() + { + if ( Platform.isClient() ) + return; + + points++; + + ItemStack processing = this.getStackInSlot( 6 ); + IGrinderEntry r = AEApi.instance().registries().grinder().getRecipeForInput( processing ); + if ( r != null ) + { + if ( r.getEnergyCost() > points ) + return; + + points = 0; + InventoryAdaptor sia = InventoryAdaptor.getAdaptor( new WrapperInventoryRange( this, 3, 3, true ), ForgeDirection.EAST ); + + addItem( sia, r.getOutput() ); + + float chance = (Platform.getRandomInt() % 2000) / 2000.0f; + if ( chance <= r.getOptionalChance() ) + addItem( sia, r.getOptionalOutput() ); + + this.setInventorySlotContents( 6, null ); + } + } + + @Override + public boolean canCrankAttach(ForgeDirection directionToCrank) + { + return getUp().equals( directionToCrank ); + } + +} diff --git a/tile/inventory/AppEngInternalInventory.java b/tile/inventory/AppEngInternalInventory.java new file mode 100644 index 00000000..1a77818b --- /dev/null +++ b/tile/inventory/AppEngInternalInventory.java @@ -0,0 +1,227 @@ +package appeng.tile.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.storage.IMEInventory; +import appeng.me.storage.MEIInventoryWrapper; +import appeng.util.Platform; + +public class AppEngInternalInventory implements IInventory +{ + + protected IAEAppEngInventory te; + int size; + int maxStack; + + protected ItemStack inv[]; + + public IMEInventory getIMEI() + { + return new MEIInventoryWrapper( this, null ); + } + + public boolean isEmpty() + { + for (int x = 0; x < getSizeInventory(); x++) + if ( getStackInSlot( x ) != null ) + return false; + return true; + } + + public AppEngInternalInventory(IAEAppEngInventory _te, int s) { + te = _te; + size = s; + maxStack = 64; + inv = new ItemStack[s]; + } + + public void setMaxStackSize(int s) + { + maxStack = s; + } + + @Override + public ItemStack getStackInSlot(int var1) + { + return inv[var1]; + } + + @Override + public ItemStack decrStackSize(int slot, int qty) + { + if ( inv[slot] != null ) + { + ItemStack split = getStackInSlot( slot ); + ItemStack ns = null; + + if ( qty >= split.stackSize ) + { + ns = inv[slot]; + inv[slot] = null; + } + else + ns = split.splitStack( qty ); + + if ( te != null && Platform.isServer() ) + { + te.onChangeInventory( this, slot, InvOperation.decrStackSize, ns, null ); + } + + return ns; + } + + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int var1) + { + return null; + } + + @Override + public void setInventorySlotContents(int slot, ItemStack newItemStack) + { + ItemStack oldStack = inv[slot]; + inv[slot] = newItemStack; + + if ( te != null && Platform.isServer() ) + { + ItemStack removed = oldStack; + ItemStack added = newItemStack; + + if ( oldStack != null && newItemStack != null && Platform.isSameItem( oldStack, newItemStack ) ) + { + if ( oldStack.stackSize > newItemStack.stackSize ) + { + removed = removed.copy(); + removed.stackSize -= newItemStack.stackSize; + added = null; + } + else if ( oldStack.stackSize < newItemStack.stackSize ) + { + added = added.copy(); + added.stackSize -= oldStack.stackSize; + removed = null; + } + else + { + removed = added = null; + } + } + + te.onChangeInventory( this, slot, InvOperation.setInventorySlotContents, removed, added ); + } + } + + @Override + public void onInventoryChanged() + { + if ( te != null && Platform.isServer() ) + { + te.onChangeInventory( this, -1, InvOperation.onInventoryChanged, null, null ); + } + } + + @Override + public int getInventoryStackLimit() + { + return maxStack > 64 ? 64 : maxStack; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return true; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + public void writeToNBT(NBTTagCompound target) + { + for (int x = 0; x < size; x++) + { + try + { + NBTTagCompound c = new NBTTagCompound(); + + if ( inv[x] != null ) + { + inv[x].writeToNBT( c ); + } + + target.setCompoundTag( "#" + x, c ); + } + catch (Exception err) + { + } + } + } + + public void readFromNBT(NBTTagCompound target) + { + for (int x = 0; x < size; x++) + { + try + { + NBTTagCompound c = target.getCompoundTag( "#" + x ); + + if ( c != null ) + inv[x] = ItemStack.loadItemStackFromNBT( c ); + + } + catch (Exception err) + { + err.printStackTrace(); + } + } + } + + public void writeToNBT(NBTTagCompound data, String name) + { + NBTTagCompound c = new NBTTagCompound(); + writeToNBT( c ); + data.setCompoundTag( name, c ); + } + + public void readFromNBT(NBTTagCompound data, String name) + { + NBTTagCompound c = data.getCompoundTag( name ); + if ( c != null ) + readFromNBT( c ); + } + + @Override + public int getSizeInventory() + { + return size; + } + + @Override + public String getInvName() + { + return "appeng-internal"; + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } +} diff --git a/tile/inventory/IAEAppEngInventory.java b/tile/inventory/IAEAppEngInventory.java new file mode 100644 index 00000000..14975a53 --- /dev/null +++ b/tile/inventory/IAEAppEngInventory.java @@ -0,0 +1,13 @@ +package appeng.tile.inventory; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public interface IAEAppEngInventory +{ + + IInventory getInternalInventory(); + + void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack); + +} diff --git a/tile/inventory/InvOperation.java b/tile/inventory/InvOperation.java new file mode 100644 index 00000000..731a0fea --- /dev/null +++ b/tile/inventory/InvOperation.java @@ -0,0 +1,7 @@ +package appeng.tile.inventory; + +public enum InvOperation +{ + decrStackSize, setInventorySlotContents, onInventoryChanged + +} diff --git a/tile/mac/TileMolecularAssembler.java b/tile/mac/TileMolecularAssembler.java new file mode 100644 index 00000000..ca9869b2 --- /dev/null +++ b/tile/mac/TileMolecularAssembler.java @@ -0,0 +1,30 @@ +package appeng.tile.mac; + +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.tile.grid.AENetworkTile; + +public class TileMolecularAssembler extends AENetworkTile implements IAEMultiBlock +{ + + @Override + public void disconnect() + { + // TODO Auto-generated method stub + } + + @Override + public IAECluster getCluster() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isValid() + { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/tile/mac/TilePatternProvider.java b/tile/mac/TilePatternProvider.java new file mode 100644 index 00000000..4e2f6004 --- /dev/null +++ b/tile/mac/TilePatternProvider.java @@ -0,0 +1,30 @@ +package appeng.tile.mac; + +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.tile.grid.AENetworkTile; + +public class TilePatternProvider extends AENetworkTile implements IAEMultiBlock +{ + + @Override + public void disconnect() + { + // TODO Auto-generated method stub + } + + @Override + public IAECluster getCluster() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isValid() + { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/tile/misc/TileCharger.java b/tile/misc/TileCharger.java new file mode 100644 index 00000000..c4e0d90b --- /dev/null +++ b/tile/misc/TileCharger.java @@ -0,0 +1,249 @@ +package appeng.tile.misc; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.config.PowerUnits; +import appeng.api.implementations.IAEItemPowerStorage; +import appeng.api.implementations.ICrankable; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.AECableType; +import appeng.me.GridAccessException; +import appeng.server.AccessType; +import appeng.server.Security; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; + +public class TileCharger extends AENetworkPowerTile implements ICrankable +{ + + final int sides[] = new int[] { 0 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); + int tickTickTimer = 0; + + int lastUpdate = 0; + boolean requiresUpdate = false; + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + private class TileChargerHandler extends AETileEventHandler + { + + public TileChargerHandler() { + super( EnumSet.of( TileEventType.TICK, TileEventType.NETWORK ) ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + try + { + IAEItemStack item = AEItemStack.loadItemStackFromPacket( data ); + ItemStack is = item.getItemStack(); + inv.setInventorySlotContents( 0, is ); + } + catch (Throwable t) + { + inv.setInventorySlotContents( 0, null ); + } + return false; // TESR dosn't need updates! + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + AEItemStack is = AEItemStack.create( getStackInSlot( 0 ) ); + if ( is != null ) + is.writeToPacket( data ); + } + + @Override + public void Tick() + { + if ( lastUpdate > 60 && requiresUpdate ) + { + requiresUpdate = false; + markForUpdate(); + lastUpdate = 0; + } + lastUpdate++; + + tickTickTimer++; + if ( tickTickTimer < 20 ) + return; + tickTickTimer = 0; + + ItemStack myItem = getStackInSlot( 0 ); + + // charge from the network! + if ( internalCurrentPower < 1499 ) + { + try + { + injectExternalPower( PowerUnits.AE, + gridProxy.getEnergy().extractAEPower( Math.min( 150.0, 1500.0 - internalCurrentPower ), Actionable.MODULATE, PowerMultiplier.ONE ) ); + tickTickTimer = 20; // keep tickin... + } + catch (GridAccessException e) + { + // continue! + } + } + + if ( myItem == null ) + return; + + if ( internalCurrentPower > 149 && Platform.isChargeable( myItem ) ) + { + IAEItemPowerStorage ps = (IAEItemPowerStorage) myItem.getItem(); + if ( ps.getAEMaxPower( myItem ) > ps.getAECurrentPower( myItem ) ) + { + double oldPower = internalCurrentPower; + + double adjustment = ps.injectAEPower( myItem, extractAEPower( 150.0, Actionable.MODULATE, PowerMultiplier.CONFIG ) ); + internalCurrentPower += adjustment; + if ( oldPower > internalCurrentPower ) + requiresUpdate = true; + tickTickTimer = 20; // keep tickin... + } + } + else if ( internalCurrentPower > 1499 && AEApi.instance().materials().materialCertusQuartzCrystal.sameAs( myItem ) ) + { + if ( Platform.getRandomFloat() > 0.8f ) // simulate wait + { + extractAEPower( internalMaxPower, Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 + setInventorySlotContents( 0, AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( myItem.stackSize ) ); + } + } + } + + }; + + public TileCharger() { + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + internalMaxPower = 1500; + gridProxy.setIdlePowerUsage( 0 ); + addNewHandler( new TileChargerHandler() ); + } + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + super.setOrientation( inForward, inUp ); + gridProxy.setValidSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + setPowerSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + } + + @Override + public boolean canTurn() + { + return internalCurrentPower < internalMaxPower; + } + + @Override + public void applyTurn() + { + injectExternalPower( PowerUnits.AE, 150 ); + + ItemStack myItem = getStackInSlot( 0 ); + if ( internalCurrentPower > 1499 && AEApi.instance().materials().materialCertusQuartzCrystal.sameAs( myItem ) ) + { + extractAEPower( internalMaxPower, Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 + setInventorySlotContents( 0, AEApi.instance().materials().materialCertusQuartzCrystalCharged.stack( myItem.stackSize ) ); + } + } + + @Override + public boolean canCrankAttach(ForgeDirection directionToCrank) + { + return getUp().equals( directionToCrank ) || getUp().getOpposite().equals( directionToCrank ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + markForUpdate(); + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public int getInventoryStackLimit() + { + return 1; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return Platform.isChargeable( itemstack ) || AEApi.instance().materials().materialCertusQuartzCrystal.sameAs( itemstack ); + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + if ( Platform.isChargeable( itemstack ) ) + { + IAEItemPowerStorage ips = (IAEItemPowerStorage) itemstack.getItem(); + if ( ips.getAECurrentPower( itemstack ) >= ips.getAEMaxPower( itemstack ) ) + return true; + } + + return AEApi.instance().materials().materialCertusQuartzCrystalCharged.sameAs( itemstack ); + } + + public void activate(EntityPlayer player) + { + if ( !Security.hasPermissions( this, player, AccessType.BLOCK_ACCESS ) ) + return; + + ItemStack myItem = getStackInSlot( 0 ); + if ( myItem == null ) + { + ItemStack held = player.inventory.getCurrentItem(); + if ( AEApi.instance().materials().materialCertusQuartzCrystal.sameAs( held ) || Platform.isChargeable( held ) ) + { + held = player.inventory.decrStackSize( player.inventory.currentItem, 1 ); + setInventorySlotContents( 0, held ); + } + } + else + { + List drops = new ArrayList(); + drops.add( myItem ); + setInventorySlotContents( 0, null ); + Platform.spawnDrops( worldObj, xCoord + getForward().offsetX, yCoord + getForward().offsetY, zCoord + getForward().offsetZ, drops ); + } + } + +} diff --git a/tile/misc/TileCondenser.java b/tile/misc/TileCondenser.java new file mode 100644 index 00000000..7104c469 --- /dev/null +++ b/tile/misc/TileCondenser.java @@ -0,0 +1,251 @@ +package appeng.tile.misc; + +import java.util.EnumSet; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; +import appeng.api.AEApi; +import appeng.api.config.CondenserOuput; +import appeng.api.config.Settings; +import appeng.api.implementations.IStorageComponent; +import appeng.api.util.IConfigManager; +import appeng.api.util.IConfigureableObject; +import appeng.tile.AEBaseInvTile; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.IAEAppEngInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.ConfigManager; +import appeng.util.IConfigManagerHost; +import appeng.util.Platform; + +public class TileCondenser extends AEBaseInvTile implements IAEAppEngInventory, IFluidHandler, IConfigManagerHost, IConfigureableObject +{ + + int sides[] = new int[] { 0, 1 }; + static private FluidTankInfo[] empty = new FluidTankInfo[] { new FluidTankInfo( null, 10 ) }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 3 ); + ConfigManager cm = new ConfigManager( this ); + + public double storedPower = 0; + + private class TileCondenserHandler extends AETileEventHandler + { + + public TileCondenserHandler() { + super( EnumSet.of( TileEventType.WORLD_NBT ) ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setDouble( "storedPower", storedPower ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + storedPower = data.getDouble( "storedPower" ); + } + + }; + + public TileCondenser() { + addNewHandler( new TileCondenserHandler() ); + cm.registerSetting( Settings.CONDENSER_OUTPUT, CondenserOuput.TRASH ); + } + + public double getStorage() + { + ItemStack is = inv.getStackInSlot( 2 ); + if ( is != null ) + { + if ( is.getItem() instanceof IStorageComponent ) + { + IStorageComponent sc = (IStorageComponent) is.getItem(); + if ( sc.isStorageComponent( is ) ) + return sc.getBytes( is ) * 8; + } + } + return 0; + } + + public void addPower(double rawPower) + { + storedPower += rawPower; + storedPower = Math.max( 0.0, Math.min( getStorage(), storedPower ) ); + + double requiredPower = getRequiredPower(); + ItemStack output = getOutput(); + while (requiredPower <= storedPower && output != null && requiredPower > 0) + { + if ( canAddOutput( output ) ) + { + storedPower -= requiredPower; + addOutput( output ); + } + else + break; + } + + } + + private boolean canAddOutput(ItemStack output) + { + ItemStack outputStack = getStackInSlot( 1 ); + return outputStack == null || (Platform.isSameItem( outputStack, output ) && outputStack.stackSize < outputStack.getMaxStackSize()); + } + + /** + * make sure you validate with canAddOutput prior to this. + * + * @param output + */ + private void addOutput(ItemStack output) + { + ItemStack outputStack = getStackInSlot( 1 ); + if ( outputStack == null ) + setInventorySlotContents( 1, output.copy() ); + else + { + outputStack.stackSize++; + setInventorySlotContents( 1, outputStack ); + } + } + + private ItemStack getOutput() + { + switch ((CondenserOuput) cm.getSetting( Settings.CONDENSER_OUTPUT )) + { + case MATTER_BALLS: + return AEApi.instance().materials().materialMatterBall.stack( 1 ); + case SINGULARITY: + return AEApi.instance().materials().materialSingularity.stack( 1 ); + case TRASH: + default: + } + return null; + } + + public double getRequiredPower() + { + return ((CondenserOuput) cm.getSetting( Settings.CONDENSER_OUTPUT )).requiredPower; + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemstack) + { + if ( i == 0 ) + { + if ( itemstack != null ) + addPower( itemstack.stackSize ); + } + else + { + inv.setInventorySlotContents( 1, itemstack ); + } + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return i == 0; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return i != 0; + } + + @Override + public boolean canInsertItem(int i, ItemStack itemstack, int j) + { + return i == 0; + } + + @Override + public int[] getAccessibleSlotsFromSide(int var1) + { + return sides; + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + if ( slot == 0 ) + { + ItemStack is = inv.getStackInSlot( 0 ); + if ( is != null ) + { + addPower( is.stackSize ); + inv.setInventorySlotContents( 0, null ); + } + } + } + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) + { + if ( doFill ) + addPower( (resource == null ? 0.0 : (double) resource.amount) / 500.0 ); + + return resource == null ? 0 : resource.amount; + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) + { + return null; + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) + { + return null; + } + + @Override + public boolean canFill(ForgeDirection from, Fluid fluid) + { + return true; + } + + @Override + public boolean canDrain(ForgeDirection from, Fluid fluid) + { + return false; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) + { + return empty; + } + + @Override + public void updateSetting(Enum settingName, Enum newValue) + { + addPower( 0 ); + } + + @Override + public IConfigManager getConfigManager() + { + return cm; + } + +} diff --git a/tile/misc/TileInscriber.java b/tile/misc/TileInscriber.java new file mode 100644 index 00000000..5e744439 --- /dev/null +++ b/tile/misc/TileInscriber.java @@ -0,0 +1,117 @@ +package appeng.tile.misc; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.AECableType; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileInscriber extends AENetworkPowerTile +{ + + final int sides[] = new int[] { 0, 1 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 ); + int processingTime = 0; + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + private class TileInscriberHandler extends AETileEventHandler + { + + public TileInscriberHandler() { + super( EnumSet.of( TileEventType.TICK, TileEventType.NETWORK ) ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + + return false; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + + } + + @Override + public void Tick() + { + + } + + }; + + public TileInscriber() { + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + internalMaxPower = 1500; + gridProxy.setIdlePowerUsage( 0 ); + addNewHandler( new TileInscriberHandler() ); + } + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + super.setOrientation( inForward, inUp ); + gridProxy.setValidSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + setPowerSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public int getInventoryStackLimit() + { + return 1; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return i == 0; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return i == 1; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + public void activate(EntityPlayer player) + { + // TODO Auto-generated method stub + + } + +} diff --git a/tile/misc/TileInterface.java b/tile/misc/TileInterface.java new file mode 100644 index 00000000..84f0911a --- /dev/null +++ b/tile/misc/TileInterface.java @@ -0,0 +1,133 @@ +package appeng.tile.misc; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.implementations.IStorageMonitorable; +import appeng.api.networking.IGridNode; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.me.GridAccessException; +import appeng.me.storage.MEMonitorPassthu; +import appeng.me.storage.NullInventory; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileInterface extends AENetworkInvTile implements IGridTickable, IStorageMonitorable +{ + + final int sides[] = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 16 + 9 ); + + MEMonitorPassthu items = new MEMonitorPassthu( new NullInventory() ); + MEMonitorPassthu fluids = new MEMonitorPassthu( new NullInventory() ); + + @Override + public void gridChanged() + { + try + { + items.setInternal( gridProxy.getStorage().getItemInventory() ); + fluids.setInternal( gridProxy.getStorage().getFluidInventory() ); + } + catch (GridAccessException gae) + { + items.setInternal( new NullInventory() ); + fluids.setInternal( new NullInventory() ); + } + + worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, 0 ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + if ( slot >= 16 ) + { + // gridProxy.getCrafting() + } + else + updateStorage(); + } + + public boolean hasWorkToDo() + { + // TODO Auto-generated method stub + return false; + } + + private boolean updateStorage() + { + // TODO Auto-generated method stub + return false; + } + + public boolean hasConfig() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public TickingRequest getTickingRequest(IGridNode node) + { + return new TickingRequest( 5, 120, !hasWorkToDo(), false ); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) + { + boolean couldDoWork = updateStorage(); + return hasWorkToDo() ? (couldDoWork ? TickRateModulation.URGENT : TickRateModulation.SLOWER) : TickRateModulation.SLEEP; + } + + @Override + public IMEMonitor getItemInventory() + { + if ( hasConfig() ) + return null; + + return items; + } + + @Override + public IMEMonitor getFluidInventory() + { + if ( hasConfig() ) + return null; + + return fluids; + } + +} diff --git a/tile/misc/TileNetworkEmitter.java b/tile/misc/TileNetworkEmitter.java new file mode 100644 index 00000000..89f27c40 --- /dev/null +++ b/tile/misc/TileNetworkEmitter.java @@ -0,0 +1,22 @@ +package appeng.tile.misc; + +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.common.ForgeDirection; +import appeng.tile.grid.AENetworkTile; + +public class TileNetworkEmitter extends AENetworkTile +{ + + public TileNetworkEmitter() { + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + } + + public void activate(EntityPlayer player) + { + // TODO Auto-generated method stub + + } + +} diff --git a/tile/misc/TilePartitionerEditor.java b/tile/misc/TilePartitionerEditor.java new file mode 100644 index 00000000..76062db3 --- /dev/null +++ b/tile/misc/TilePartitionerEditor.java @@ -0,0 +1,8 @@ +package appeng.tile.misc; + +import appeng.tile.AEBaseTile; + +public class TilePartitionerEditor extends AEBaseTile +{ + +} diff --git a/tile/misc/TileQuartzCrystalizer.java b/tile/misc/TileQuartzCrystalizer.java new file mode 100644 index 00000000..c295463f --- /dev/null +++ b/tile/misc/TileQuartzCrystalizer.java @@ -0,0 +1,83 @@ +package appeng.tile.misc; + +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.AECableType; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileQuartzCrystalizer extends AENetworkPowerTile +{ + + final int sides[] = new int[] { 0, 1 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 ); + int processingTime = 0; + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + public TileQuartzCrystalizer() { + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + internalMaxPower = 1500; + gridProxy.setIdlePowerUsage( 0 ); + } + + @Override + public void setOrientation(ForgeDirection inForward, ForgeDirection inUp) + { + super.setOrientation( inForward, inUp ); + gridProxy.setValidSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + setPowerSides( EnumSet.of( getUp(), getUp().getOpposite() ) ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public int getInventoryStackLimit() + { + return 1; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return i == 0; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return i == 1; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + public void activate(EntityPlayer player) + { + // TODO Auto-generated method stub + + } + +} diff --git a/tile/misc/TileVibrationChamber.java b/tile/misc/TileVibrationChamber.java new file mode 100644 index 00000000..9efebcfb --- /dev/null +++ b/tile/misc/TileVibrationChamber.java @@ -0,0 +1,245 @@ +package appeng.tile.misc; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.Actionable; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.me.GridAccessException; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileVibrationChamber extends AENetworkInvTile implements IGridTickable +{ + + final double powerPerTick = 5; + + final int sides[] = new int[] { 0 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); + + public int burnSpeed = 100; + public double burnTime = 0; + public double maxBurnTime = 0; + + // client side.. + public boolean isOn; + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + private class TileVibrationChamberHandler extends AETileEventHandler + { + + public TileVibrationChamberHandler() { + super( EnumSet.of( TileEventType.NETWORK, TileEventType.WORLD_NBT ) ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + boolean wasOn = isOn; + isOn = data.readBoolean(); + return wasOn != isOn; // TESR dosn't need updates! + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + data.writeBoolean( burnTime > 0 ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setDouble( "burnTime", burnTime ); + data.setDouble( "maxBurnTime", maxBurnTime ); + data.setInteger( "burnSpeed", burnSpeed ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + burnTime = data.getDouble( "burnTime" ); + maxBurnTime = data.getDouble( "maxBurnTime" ); + burnSpeed = data.getInteger( "burnSpeed" ); + } + + }; + + public TileVibrationChamber() { + gridProxy.setIdlePowerUsage( 0 ); + addNewHandler( new TileVibrationChamberHandler() ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + if ( burnTime <= 0 ) + { + eatFuel(); + + if ( burnTime > 0 ) + { + try + { + gridProxy.getTick().wakeDevice( gridProxy.getNode() ); + } + catch (GridAccessException e) + { + // wake up! + } + } + } + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return TileEntityFurnace.getItemBurnTime( itemstack ) > 0; + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return false; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public TickingRequest getTickingRequest(IGridNode node) + { + if ( burnTime <= 0 ) + eatFuel(); + + return new TickingRequest( 10, 40, burnTime <= 0, false ); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) + { + if ( burnTime <= 0 ) + { + eatFuel(); + + if ( burnTime > 0 ) + return TickRateModulation.URGENT; + + burnSpeed = 100; + return TickRateModulation.SLEEP; + } + + burnSpeed = Math.max( 20, Math.min( burnSpeed, 200 ) ); + double dialiation = burnSpeed / 100.0; + + double timePassed = (double) TicksSinceLastCall * dialiation; + burnTime -= timePassed; + if ( burnTime < 0 ) + { + timePassed += burnTime; + burnTime = 0; + } + + try + { + IEnergyGrid grid = gridProxy.getEnergy(); + double newPower = timePassed * powerPerTick; + double overFlow = grid.injectPower( newPower, Actionable.SIMULATE ); + + // burn the over flow. + grid.injectPower( Math.max( 0.0, newPower - overFlow ), Actionable.MODULATE ); + + if ( overFlow > 0 ) + burnSpeed -= TicksSinceLastCall; + else + burnSpeed += TicksSinceLastCall; + + burnSpeed = Math.max( 20, Math.min( burnSpeed, 200 ) ); + return overFlow > 0 ? TickRateModulation.SLOWER : TickRateModulation.FASTER; + } + catch (GridAccessException e) + { + burnSpeed -= TicksSinceLastCall; + burnSpeed = Math.max( 20, Math.min( burnSpeed, 200 ) ); + return TickRateModulation.SLOWER; + } + } + + private void eatFuel() + { + ItemStack is = getStackInSlot( 0 ); + if ( is != null ) + { + int newBurnTime = TileEntityFurnace.getItemBurnTime( is ); + if ( newBurnTime > 0 && is.stackSize > 0 ) + { + burnTime += newBurnTime; + maxBurnTime = burnTime; + is.stackSize--; + if ( is.stackSize <= 0 ) + setInventorySlotContents( 0, null ); + else + setInventorySlotContents( 0, is ); + } + } + + if ( burnTime > 0 ) + { + try + { + gridProxy.getTick().wakeDevice( gridProxy.getNode() ); + } + catch (GridAccessException e) + { + // gah! + } + } + + if ( (!isOn && burnTime > 0) || (isOn && burnTime <= 0) ) + { + isOn = burnTime > 0; + markForUpdate(); + } + } +} diff --git a/tile/networking/TileCableBus.java b/tile/networking/TileCableBus.java new file mode 100644 index 00000000..1f7bb417 --- /dev/null +++ b/tile/networking/TileCableBus.java @@ -0,0 +1,252 @@ +package appeng.tile.networking; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridNode; +import appeng.api.parts.IFacadeContainer; +import appeng.api.parts.IPart; +import appeng.api.parts.SelectedPart; +import appeng.api.util.AECableType; +import appeng.api.util.AEColor; +import appeng.api.util.DimensionalCoord; +import appeng.helpers.AEMultiTile; +import appeng.helpers.ICustomCollision; +import appeng.helpers.TickHandler; +import appeng.parts.CableBusContainer; +import appeng.tile.AEBaseTile; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; + +public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomCollision +{ + + public CableBusContainer cb = new CableBusContainer( this ); + private int oldLV = -1; // on re-calculate light when it changes + + class CableBusHandler extends AETileEventHandler + { + + public CableBusHandler() { + super( EnumSet.of( TileEventType.NETWORK, TileEventType.WORLD_NBT ) ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + cb.readFromNBT( data ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + cb.writeToNBT( data ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + boolean ret = cb.readFromStream( data ); + + int newLV = cb.getLightValue(); + if ( newLV != oldLV ) + { + oldLV = newLV; + worldObj.updateAllLightTypes( xCoord, yCoord, zCoord ); + } + + return ret; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + cb.writeToStream( data ); + } + + }; + + @Override + public void onReady() + { + super.onReady(); + if ( cb.isEmpty() ) + worldObj.destroyBlock( xCoord, yCoord, zCoord, true ); + else + cb.addToWorld(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + cb.removeFromWorld(); + } + + @Override + public void validate() + { + super.validate(); + TickHandler.instance.addInit( this ); + } + + @Override + public void invalidate() + { + super.invalidate(); + cb.removeFromWorld(); + } + + @Override + public boolean canBeRotated() + { + return false; + } + + @Override + public void getDrops(World w, int x, int y, int z, ArrayList drops) + { + cb.getDrops( drops ); + } + + public TileCableBus() { + addNewHandler( new CableBusHandler() ); + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) + { + return cb.getGridNode( dir ); + } + + @Override + public boolean canAddPart(ItemStack is, ForgeDirection side) + { + return cb.canAddPart( is, side ); + } + + @Override + public ForgeDirection addPart(ItemStack is, ForgeDirection side) + { + return cb.addPart( is, side ); + } + + @Override + public void removePart(ForgeDirection side) + { + cb.removePart( side ); + } + + @Override + public IPart getPart(ForgeDirection side) + { + return cb.getPart( side ); + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public TileEntity getTile() + { + return this; + } + + @Override + public Iterable getSelectedBoundingBoxsFromPool(World w, int x, int y, int z) + { + return cb.getSelectedBoundingBoxsFromPool( false ); + } + + @Override + public void addCollidingBlockToList(World w, int x, int y, int z, AxisAlignedBB bb, List out, Entity e) + { + for (AxisAlignedBB bx : getSelectedBoundingBoxsFromPool( w, x, y, z )) + out.add( AxisAlignedBB.getAABBPool().getAABB( bx.minX, bx.minY, bx.minZ, bx.maxX, bx.maxY, bx.maxZ ) ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection side) + { + return cb.getCableConnectionType( side ); + } + + @Override + public AEColor getColor() + { + return cb.getColor(); + } + + @Override + public IFacadeContainer getFacadeContainer() + { + return cb.getFacadeContainer(); + } + + @Override + public void clearContainer() + { + cb = new CableBusContainer( this ); + } + + @Override + public boolean isBlocked(ForgeDirection side) + { + return false; + } + + @Override + public void markForUpdate() + { + if ( worldObj == null ) + return; + + int newLV = cb.getLightValue(); + if ( newLV != oldLV ) + { + oldLV = newLV; + worldObj.updateAllLightTypes( xCoord, yCoord, zCoord ); + } + + super.markForUpdate(); + } + + @Override + public SelectedPart selectPart(Vec3 pos) + { + return cb.selectPart( pos ); + } + + @Override + public void PartChanged() + { + // nothing! + } + + @Override + public void markForSave() + { + onInventoryChanged(); + } + + @Override + public boolean hasRedstone(ForgeDirection side) + { + return cb.hasRedstone( side ); + } +} diff --git a/tile/networking/TileController.java b/tile/networking/TileController.java new file mode 100644 index 00000000..09a11707 --- /dev/null +++ b/tile/networking/TileController.java @@ -0,0 +1,171 @@ +package appeng.tile.networking; + +import java.util.EnumSet; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.Actionable; +import appeng.api.networking.GridFlags; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.networking.events.MENetworkControllerChange; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.events.MENetworkPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType; +import appeng.api.networking.pathing.ControllerState; +import appeng.me.GridAccessException; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileController extends AENetworkPowerTile implements IAEPowerStorage +{ + + boolean isValid = false; + + public TileController() { + internalMaxPower = 8000; + internalPublicPowerStorage = true; + gridProxy.setIdlePowerUsage( 6 ); + gridProxy.setFlags( GridFlags.CANNOT_CARRY ); + } + + @Override + protected double getFunnelPowerDemand() + { + try + { + return gridProxy.getEnergy().getEnergyDemand( 8000 ); + } + catch (GridAccessException e) + { + // no grid? use local... + return super.getFunnelPowerDemand(); + } + } + + @Override + protected double funnelPowerIntoStorage(double AEUnits, Actionable mode) + { + try + { + double ret = gridProxy.getEnergy().injectPower( AEUnits, mode ); + if ( mode == Actionable.SIMULATE ) + return ret; + return 0; + } + catch (GridAccessException e) + { + // no grid? use local... + return super.funnelPowerIntoStorage( AEUnits, mode ); + } + } + + @Override + protected void PowerEvent(PowerEventType x) + { + try + { + gridProxy.getGrid().postEvent( new MENetworkPowerStorage( this, x ) ); + } + catch (GridAccessException e) + { + // not ready! + } + } + + @MENetworkEventSubscribe + public void onPowerChange(MENetworkControllerChange status) + { + updateMeta(); + } + + @MENetworkEventSubscribe + public void onPowerChange(MENetworkPowerStatusChange status) + { + updateMeta(); + } + + @Override + public void onReady() + { + onNeighborChange( true ); + super.onReady(); + } + + public void onNeighborChange(boolean force) + { + boolean xx = worldObj.getBlockTileEntity( xCoord - 1, yCoord, zCoord ) instanceof TileController + && worldObj.getBlockTileEntity( xCoord + 1, yCoord, zCoord ) instanceof TileController; + boolean yy = worldObj.getBlockTileEntity( xCoord, yCoord - 1, zCoord ) instanceof TileController + && worldObj.getBlockTileEntity( xCoord, yCoord + 1, zCoord ) instanceof TileController; + boolean zz = worldObj.getBlockTileEntity( xCoord, yCoord, zCoord - 1 ) instanceof TileController + && worldObj.getBlockTileEntity( xCoord, yCoord, zCoord + 1 ) instanceof TileController; + + // int meta = world.getBlockMetadata( xCoord, yCoord, zCoord ); + // boolean hasPower = meta > 0; + // boolean isConflict = meta == 2; + + boolean oldValid = isValid; + + isValid = (xx && !yy && !zz) || (!xx && yy && !zz) || (!xx && !yy && zz) || ((xx ? 1 : 0) + (yy ? 1 : 0) + (zz ? 1 : 0) <= 1); + + if ( oldValid != isValid || force ) + { + if ( isValid ) + gridProxy.setValidSides( EnumSet.allOf( ForgeDirection.class ) ); + else + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + } + + updateMeta(); + } + + private void updateMeta() + { + if ( !gridProxy.isReady() ) + return; + + int meta = 0; + + try + { + if ( gridProxy.getEnergy().isNetworkPowered() ) + { + meta = 1; + + if ( gridProxy.getPath().getControllerState() == ControllerState.CONTROLLER_CONFLICT ) + meta = 2; + } + } + catch (GridAccessException e) + { + meta = 0; + } + + worldObj.setBlockMetadataWithNotify( xCoord, yCoord, zCoord, meta, 2 ); + } + + final int sides[] = new int[] { 0 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + +} diff --git a/tile/networking/TileCreativeEnergyCell.java b/tile/networking/TileCreativeEnergyCell.java new file mode 100644 index 00000000..a06f01c4 --- /dev/null +++ b/tile/networking/TileCreativeEnergyCell.java @@ -0,0 +1,60 @@ +package appeng.tile.networking; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.util.AECableType; +import appeng.tile.grid.AENetworkTile; + +public class TileCreativeEnergyCell extends AENetworkTile implements IAEPowerStorage +{ + + public TileCreativeEnergyCell() { + gridProxy.setIdlePowerUsage( 0 ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + @Override + public double injectAEPower(double amt, Actionable mode) + { + return 0; + } + + @Override + public double extractAEPower(double amt, Actionable mode, PowerMultiplier pm) + { + return amt; + } + + @Override + public double getAEMaxPower() + { + return Integer.MAX_VALUE; + } + + @Override + public double getAECurrentPower() + { + return Integer.MAX_VALUE - 32; + } + + @Override + public boolean isAEPublicPowerStorage() + { + return true; + } + + @Override + public AccessRestriction getPowerFlow() + { + return AccessRestriction.READ_WRITE; + } + +} diff --git a/tile/networking/TileDenseEnergyCell.java b/tile/networking/TileDenseEnergyCell.java new file mode 100644 index 00000000..3442f7ab --- /dev/null +++ b/tile/networking/TileDenseEnergyCell.java @@ -0,0 +1,10 @@ +package appeng.tile.networking; + +public class TileDenseEnergyCell extends TileEnergyCell +{ + + public TileDenseEnergyCell() { + internalMaxPower = 200000 * 8; + } + +} diff --git a/tile/networking/TileEnergyAcceptor.java b/tile/networking/TileEnergyAcceptor.java new file mode 100644 index 00000000..17007af7 --- /dev/null +++ b/tile/networking/TileEnergyAcceptor.java @@ -0,0 +1,85 @@ +package appeng.tile.networking; + +import java.util.EnumSet; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.util.AECableType; +import appeng.me.GridAccessException; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileEnergyAcceptor extends AENetworkPowerTile +{ + + final int sides[] = new int[] {}; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 0 ); + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + private class TilePowerRelayHandler extends AETileEventHandler + { + + public TilePowerRelayHandler() { + super( EnumSet.of( TileEventType.TICK ) ); + } + + @Override + public void Tick() + { + if ( internalCurrentPower > 0 ) + { + try + { + IEnergyGrid eg = gridProxy.getEnergy(); + double powerRequested = internalCurrentPower - eg.injectPower( internalCurrentPower, Actionable.SIMULATE ); + + if ( powerRequested > 0 ) + { + internalCurrentPower += eg.injectPower( extractAEPower( powerRequested, Actionable.MODULATE, PowerMultiplier.ONE ), Actionable.MODULATE ); + } + } + catch (GridAccessException e) + { + // null net, probably bads. + } + + } + } + }; + + public TileEnergyAcceptor() { + gridProxy.setIdlePowerUsage( 1.0 / 16.0 ); + addNewHandler( new TilePowerRelayHandler() ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + +} diff --git a/tile/networking/TileEnergyCell.java b/tile/networking/TileEnergyCell.java new file mode 100644 index 00000000..c0aff4a9 --- /dev/null +++ b/tile/networking/TileEnergyCell.java @@ -0,0 +1,210 @@ +package appeng.tile.networking; + +import java.util.EnumSet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType; +import appeng.api.util.AECableType; +import appeng.me.GridAccessException; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkTile; +import appeng.util.SettingsFrom; + +public class TileEnergyCell extends AENetworkTile implements IAEPowerStorage +{ + + protected double internalCurrentPower = 0.0; + protected double internalMaxPower = 200000.0; + + private byte currentMeta = -1; + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.COVERED; + } + + private void changePowerLevel() + { + byte leel = (byte) (8.0 * (internalCurrentPower / internalMaxPower)); + + if ( leel > 7 ) + leel = 7; + if ( leel < 0 ) + leel = 0; + + if ( currentMeta != leel ) + { + currentMeta = leel; + worldObj.setBlockMetadataWithNotify( xCoord, yCoord, zCoord, currentMeta, 2 ); + } + } + + private class TileEnergyCellHandler extends AETileEventHandler + { + + public TileEnergyCellHandler() { + super( EnumSet.of( TileEventType.WORLD_NBT ) ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setDouble( "internalCurrentPower", internalCurrentPower ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + internalCurrentPower = data.getDouble( "internalCurrentPower" ); + } + + }; + + public TileEnergyCell() { + gridProxy.setIdlePowerUsage( 0 ); + addNewHandler( new TileEnergyCellHandler() ); + } + + @Override + public boolean canBeRotated() + { + return false; + } + + @Override + final public double injectAEPower(double amt, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + double fakeBattery = internalCurrentPower + amt; + if ( fakeBattery > internalMaxPower ) + { + return fakeBattery - internalMaxPower; + } + + return 0; + } + + if ( internalCurrentPower < 0.01 && amt > 0.01 ) + gridProxy.getNode().getGrid().postEvent( new MENetworkPowerStorage( this, PowerEventType.PROVIDE_POWER ) ); + + internalCurrentPower += amt; + if ( internalCurrentPower > internalMaxPower ) + { + amt = internalCurrentPower - internalMaxPower; + internalCurrentPower = internalMaxPower; + + changePowerLevel(); + return amt; + } + + changePowerLevel(); + return 0; + } + + final private double extractAEPower(double amt, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + if ( internalCurrentPower > amt ) + return amt; + return internalCurrentPower; + } + + boolean wasFull = internalCurrentPower >= internalMaxPower - 0.001; + + if ( wasFull && amt > 0.001 ) + { + try + { + gridProxy.getGrid().postEvent( new MENetworkPowerStorage( this, PowerEventType.REQUEST_POWER ) ); + } + catch (GridAccessException e) + { + + } + } + + if ( internalCurrentPower > amt ) + { + internalCurrentPower -= amt; + + changePowerLevel(); + return amt; + } + + amt = internalCurrentPower; + internalCurrentPower = 0; + + changePowerLevel(); + return amt; + } + + @Override + final public double extractAEPower(double amt, Actionable mode, PowerMultiplier pm) + { + return pm.divide( extractAEPower( pm.multiply( amt ), mode ) ); + } + + @Override + public double getAEMaxPower() + { + return internalMaxPower; + } + + @Override + public double getAECurrentPower() + { + return internalCurrentPower; + } + + @Override + public boolean isAEPublicPowerStorage() + { + return true; + } + + @Override + public AccessRestriction getPowerFlow() + { + return AccessRestriction.READ_WRITE; + } + + @Override + public void onReady() + { + super.onReady(); + currentMeta = (byte) worldObj.getBlockMetadata( xCoord, yCoord, zCoord ); + changePowerLevel(); + } + + @Override + public NBTTagCompound downloadSettings(SettingsFrom from) + { + if ( from == SettingsFrom.DISMANTLE_ITEM ) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setDouble( "internalCurrentPower", internalCurrentPower ); + tag.setDouble( "internalMaxPower", internalMaxPower ); // used for tool tip. + return tag; + } + return null; + } + + @Override + public void uploadSettings(SettingsFrom from, NBTTagCompound compound) + { + if ( from == SettingsFrom.DISMANTLE_ITEM ) + { + internalCurrentPower = compound.getDouble( "internalCurrentPower" ); + } + } +} diff --git a/tile/networking/TileWireless.java b/tile/networking/TileWireless.java new file mode 100644 index 00000000..69014af1 --- /dev/null +++ b/tile/networking/TileWireless.java @@ -0,0 +1,137 @@ +package appeng.tile.networking; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.core.Configuration; +import appeng.me.GridAccessException; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileWireless extends AENetworkInvTile +{ + + public static final int POWERED_FLAG = 1; + public static final int CHANNEL_FLAG = 2; + + final int sides[] = new int[] { 0 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); + + public int clientFlags = 0; + + public TileWireless() { + gridProxy.setFlags( GridFlags.REQURE_CHANNEL ); + addNewHandler( new TileWirelessHandler() ); + } + + @MENetworkEventSubscribe + public void chanRender(MENetworkChannelsChanged c) + { + markForUpdate(); + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + markForUpdate(); + } + + class TileWirelessHandler extends AETileEventHandler + { + + public TileWirelessHandler() { + super( EnumSet.of( TileEventType.NETWORK ) ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + boolean eh = super.readFromStream( data ); + + int old = clientFlags; + clientFlags = data.readByte(); + + return eh || old != clientFlags; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + + clientFlags = 0; + + try + { + if ( gridProxy.getEnergy().isNetworkPowered() ) + clientFlags |= POWERED_FLAG; + + if ( gridProxy.getNode().meetsChannelRequirements() ) + clientFlags |= CHANNEL_FLAG; + } + catch (GridAccessException e) + { + // meh + } + + data.writeByte( (byte) clientFlags ); + } + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onReady() + { + updatePower(); + super.onReady(); + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + updatePower(); + } + + private void updatePower() + { + ItemStack boosters = inv.getStackInSlot( 0 ); + gridProxy.setIdlePowerUsage( Configuration.instance.wireless_getPowerDrain( boosters == null ? 0 : boosters.stackSize ) ); + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + +} diff --git a/tile/powersink/AEBasePoweredTile.java b/tile/powersink/AEBasePoweredTile.java new file mode 100644 index 00000000..820875d0 --- /dev/null +++ b/tile/powersink/AEBasePoweredTile.java @@ -0,0 +1,6 @@ +package appeng.tile.powersink; + +public abstract class AEBasePoweredTile extends ThermalExpansion +{ + +} diff --git a/tile/powersink/AERootPoweredTile.java b/tile/powersink/AERootPoweredTile.java new file mode 100644 index 00000000..99ba9c39 --- /dev/null +++ b/tile/powersink/AERootPoweredTile.java @@ -0,0 +1,177 @@ +package appeng.tile.powersink; + +import java.util.EnumSet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.config.PowerUnits; +import appeng.api.networking.energy.IAEPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType; +import appeng.tile.AEBaseInvTile; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; + +public abstract class AERootPoweredTile extends AEBaseInvTile implements IAEPowerStorage +{ + + // values that determin general function, are set by inheriting classes if + // needed. These should generally remain static. + protected double internalMaxPower = 10000; + protected boolean internalCanAcceptPower = true; + protected boolean internalPublicPowerStorage = false; + private EnumSet internalPowerSides = EnumSet.allOf( ForgeDirection.class ); + + protected AccessRestriction internalPowerFlow = AccessRestriction.READ_WRITE; + + // the current power buffer. + protected double internalCurrentPower = 0; + + protected void setPowerSides(EnumSet sides) + { + internalPowerSides = sides; + // trigger re-calc! + } + + protected EnumSet getPowerSides() + { + return internalPowerSides.clone(); + } + + private class AEPoweredRootHandler extends AETileEventHandler + { + + public AEPoweredRootHandler() { + super( EnumSet.of( TileEventType.WORLD_NBT ) ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setDouble( "internalCurrentPower", internalCurrentPower ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + internalCurrentPower = data.getDouble( "internalCurrentPower" ); + } + + }; + + public AERootPoweredTile() { + addNewHandler( new AEPoweredRootHandler() ); + } + + final protected double getExternalPowerDemand(PowerUnits externalUnit) + { + return PowerUnits.AE.convertTo( externalUnit, Math.max( 0.0, getFunnelPowerDemand() ) ); + } + + protected double getFunnelPowerDemand() + { + return internalMaxPower - internalCurrentPower; + } + + final public double injectExternalPower(PowerUnits input, double amt) + { + return PowerUnits.AE.convertTo( input, funnelPowerIntoStorage( input.convertTo( PowerUnits.AE, amt ), Actionable.MODULATE ) ); + } + + protected double funnelPowerIntoStorage(double AEUnits, Actionable mode) + { + return injectAEPower( AEUnits, mode ); + } + + @Override + final public double injectAEPower(double amt, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + double fakeBattery = internalCurrentPower + amt; + + if ( fakeBattery > internalMaxPower ) + return fakeBattery - internalMaxPower; + + return 0; + } + else + { + if ( internalCurrentPower < 0.01 && amt > 0.01 ) + PowerEvent( PowerEventType.PROVIDE_POWER ); + + internalCurrentPower += amt; + if ( internalCurrentPower > internalMaxPower ) + { + amt = internalCurrentPower - internalMaxPower; + internalCurrentPower = internalMaxPower; + return amt; + } + + return 0; + } + } + + protected void PowerEvent(PowerEventType x) + { + // nothing. + } + + protected double extractAEPower(double amt, Actionable mode) + { + if ( mode == Actionable.SIMULATE ) + { + if ( internalCurrentPower > amt ) + return amt; + return internalCurrentPower; + } + + boolean wasFull = internalCurrentPower >= internalMaxPower - 0.001; + if ( wasFull && amt > 0.001 ) + { + PowerEvent( PowerEventType.REQUEST_POWER ); + } + + if ( internalCurrentPower > amt ) + { + internalCurrentPower -= amt; + return amt; + } + + amt = internalCurrentPower; + internalCurrentPower = 0; + return amt; + } + + @Override + final public double extractAEPower(double amt, Actionable mode, PowerMultiplier multiplier) + { + return multiplier.divide( extractAEPower( multiplier.multiply( amt ), mode ) ); + } + + @Override + final public double getAEMaxPower() + { + return internalMaxPower; + } + + @Override + final public double getAECurrentPower() + { + return internalCurrentPower; + } + + @Override + final public boolean isAEPublicPowerStorage() + { + return internalPublicPowerStorage; + } + + @Override + final public AccessRestriction getPowerFlow() + { + return internalPowerFlow; + } +} diff --git a/tile/powersink/BuildCraft.java b/tile/powersink/BuildCraft.java new file mode 100644 index 00000000..67726ec9 --- /dev/null +++ b/tile/powersink/BuildCraft.java @@ -0,0 +1,98 @@ +package appeng.tile.powersink; + +import java.util.EnumSet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.PowerUnits; +import appeng.core.AppEng; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import buildcraft.api.power.IPowerReceptor; +import buildcraft.api.power.PowerHandler; +import buildcraft.api.power.PowerHandler.PowerReceiver; +import buildcraft.api.power.PowerHandler.Type; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.Optional.Interface; +import cpw.mods.fml.common.Optional.Method; + +@Interface(modid = "BuildCraftAPI|power", iface = "buildcraft.api.power.IPowerReceptor") +public abstract class BuildCraft extends AERootPoweredTile implements IPowerReceptor +{ + + private class BCPerdition extends AETileEventHandler + { + + final protected PowerHandler bcPowerHandler; + + public BCPerdition(IPowerReceptor te) { + super( EnumSet.of( TileEventType.TICK, TileEventType.WORLD_NBT ) ); + bcPowerHandler = new PowerHandler( te, Type.MACHINE ); + } + + @Override + public void Tick() + { + bcPowerHandler.update(); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + bcPowerHandler.writeToNBT( data, "bcPowerHandler" ); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + bcPowerHandler.readFromNBT( data, "bcPowerHandler" ); + } + + }; + + BCPerdition bcPowerWrapper; + + public BuildCraft() { + try + { + if ( Loader.isModLoaded( "BuildCraftAPI|power" ) ) + { + if ( AppEng.instance.isIntegrationEnabled( "" ) ) + addNewHandler( bcPowerWrapper = new BCPerdition( this ) ); + bcPowerWrapper.bcPowerHandler.configure( 1, 380, 1.0f / 5.0f, 1000 ); + } + } + catch (Throwable t) + { + // ignore.. no bc? + } + } + + @Override + @Method(modid = "BuildCraftAPI|power") + final public PowerReceiver getPowerReceiver(ForgeDirection side) + { + if ( internalCanAcceptPower && getPowerSides().contains( side ) ) + return bcPowerWrapper.bcPowerHandler.getPowerReceiver(); + return null; + } + + @Override + @Method(modid = "BuildCraftAPI|power") + final public void doWork(PowerHandler workProvider) + { + float requred = (float) getExternalPowerDemand( PowerUnits.MJ ); + double failed = injectExternalPower( PowerUnits.MJ, bcPowerWrapper.bcPowerHandler.useEnergy( 0.0f, requred, true ) ); + if ( failed > 0.01 ) + bcPowerWrapper.bcPowerHandler.addEnergy( (float) failed ); + } + + @Override + @Method(modid = "BuildCraftAPI|power") + final public World getWorld() + { + return worldObj; + } + +} diff --git a/tile/powersink/IC2.java b/tile/powersink/IC2.java new file mode 100644 index 00000000..8acc4223 --- /dev/null +++ b/tile/powersink/IC2.java @@ -0,0 +1,96 @@ +package appeng.tile.powersink; + +import ic2.api.energy.tile.IEnergySink; + +import java.util.EnumSet; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.common.MinecraftForge; +import appeng.api.config.PowerUnits; +import appeng.util.Platform; +import cpw.mods.fml.common.Optional.Interface; + +@Interface(modid = "IC2", iface = "ic2.api.energy.tile.IEnergySink") +public abstract class IC2 extends BuildCraft implements IEnergySink +{ + + boolean isInIC2 = false; + + @Override + final public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { + return internalCanAcceptPower && getPowerSides().contains( direction ); + } + + @Override + final public double demandedEnergyUnits() + { + return getExternalPowerDemand( PowerUnits.EU ); + } + + @Override + final public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + // just store the excess in the current block, if I return the waste, + // IC2 will just disintegrate it - Oct 20th 2013 + double overflow = PowerUnits.EU.convertTo( PowerUnits.AE, injectExternalPower( PowerUnits.EU, amount ) ); + internalCurrentPower += overflow; + return 0; // see above comment. + } + + @Override + final public int getMaxSafeInput() + { + return Integer.MAX_VALUE; + } + + @Override + public void invalidate() + { + super.invalidate(); + removeFromENet(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + removeFromENet(); + } + + @Override + public void onReady() + { + super.onReady(); + addToENet(); + } + + @Override + protected void setPowerSides(EnumSet sides) + { + super.setPowerSides( sides ); + removeFromENet(); + addToENet(); + + } + + final private void addToENet() + { + if ( !isInIC2 && Platform.isServer() ) + { + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( this ) ); + isInIC2 = true; + } + } + + final private void removeFromENet() + { + if ( isInIC2 && Platform.isServer() ) + { + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( this ) ); + isInIC2 = false; + } + } + +} diff --git a/tile/powersink/RotaryCraft.java b/tile/powersink/RotaryCraft.java new file mode 100644 index 00000000..d5332511 --- /dev/null +++ b/tile/powersink/RotaryCraft.java @@ -0,0 +1,125 @@ +package appeng.tile.powersink; + +import net.minecraftforge.common.ForgeDirection; +import Reika.RotaryCraft.API.ShaftPowerReceiver; +import appeng.api.config.PowerUnits; +import cpw.mods.fml.common.Optional.Interface; + +@Interface(modid = "RotaryCraft", iface = "Reika.RotaryCraft.API.ShaftPowerReceiver") +public abstract class RotaryCraft extends IC2 implements ShaftPowerReceiver +{ + + private int omega = 0; + private int torque = 0; + private long power = 0; + private int alpha = 0; + + @Override + final public int getOmega() + { + return omega; + } + + @Override + final public int getTorque() + { + return torque; + } + + @Override + final public long getPower() + { + return power; + } + + @Override + final public String getName() + { + return "AE"; + } + + @Override + final public int getIORenderAlpha() + { + return alpha; + } + + @Override + final public void setIORenderAlpha(int io) + { + alpha = io; + } + + @Override + final public int getMachineX() + { + return xCoord; + } + + @Override + final public int getMachineY() + { + return yCoord; + } + + @Override + final public int getMachineZ() + { + return zCoord; + } + + @Override + final public void setOmega(int o) + { + omega = o; + } + + @Override + final public void setTorque(int t) + { + torque = t; + } + + @Override + final public void setPower(long p) + { + injectExternalPower( PowerUnits.WA, p ); + power = p; + } + + @Override + final public boolean canReadFromBlock(int x, int y, int z) + { + ForgeDirection side = ForgeDirection.UNKNOWN; + + if ( x == xCoord - 1 ) + side = ForgeDirection.WEST; + else if ( x == xCoord + 1 ) + side = ForgeDirection.EAST; + else if ( z == zCoord - 1 ) + side = ForgeDirection.NORTH; + else if ( z == zCoord + 1 ) + side = ForgeDirection.SOUTH; + else if ( y == yCoord - 1 ) + side = ForgeDirection.DOWN; + else if ( y == yCoord + 1 ) + side = ForgeDirection.UP; + + return internalCanAcceptPower && getPowerSides().contains( side ); + } + + @Override + final public boolean isReceiving() + { + return true; + } + + @Override + final public void noInputMachine() + { + power = 0; + torque = 0; + omega = 0; + } + +} diff --git a/tile/powersink/ThermalExpansion.java b/tile/powersink/ThermalExpansion.java new file mode 100644 index 00000000..4d63e11c --- /dev/null +++ b/tile/powersink/ThermalExpansion.java @@ -0,0 +1,55 @@ +package appeng.tile.powersink; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.PowerUnits; +import cofh.api.energy.IEnergyHandler; +import cpw.mods.fml.common.Optional.Interface; + +@Interface(modid = "ThermalExpansion", iface = "cofh.api.energy.IEnergyHandler") +public abstract class ThermalExpansion extends RotaryCraft implements IEnergyHandler +{ + + @Override + final public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) + { + if ( simulate ) + { + double demand = getExternalPowerDemand( PowerUnits.RF ); + if ( demand > maxReceive ) + return maxReceive; + return (int) Math.floor( maxReceive - demand ); + } + else + { + double overFlow = injectExternalPower( PowerUnits.RF, maxReceive ); + double ox = Math.floor( overFlow ); + internalCurrentPower += PowerUnits.RF.convertTo( PowerUnits.AE, overFlow - ox ); + return maxReceive - (int) ox; + } + } + + @Override + final public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) + { + return 0; + } + + @Override + final public boolean canInterface(ForgeDirection from) + { + return internalCanAcceptPower && getPowerSides().contains( from ); + } + + @Override + final public int getEnergyStored(ForgeDirection from) + { + return (int) Math.floor( PowerUnits.AE.convertTo( PowerUnits.RF, getAECurrentPower() ) ); + } + + @Override + final public int getMaxEnergyStored(ForgeDirection from) + { + return (int) Math.floor( PowerUnits.AE.convertTo( PowerUnits.RF, getAEMaxPower() ) ); + } + +} diff --git a/tile/powersink/UniversalElectricity.java b/tile/powersink/UniversalElectricity.java new file mode 100644 index 00000000..a17efbe2 --- /dev/null +++ b/tile/powersink/UniversalElectricity.java @@ -0,0 +1,65 @@ +package appeng.tile.powersink; + +/* +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.core.block.IElectrical; +import universalelectricity.core.electricity.ElectricityPack; +import appeng.api.config.PowerUnits; + +public abstract class UniversalElectricity extends ThermalExpansion implements IElectrical +{ + + @Override + final public boolean canConnect(ForgeDirection direction) + { + return internalCanAcceptPower && getPowerSides().contains( direction ); + } + + @Override + final public float receiveElectricity(ForgeDirection from, ElectricityPack receive, boolean doReceive) + { + float accepted = 0; + double recievedPower = receive.getWatts(); + + if ( doReceive ) + { + accepted = (float) (recievedPower - injectExternalPower( PowerUnits.KJ, recievedPower )); + } + else + { + double whatIWant = getExternalPowerDemand( PowerUnits.KJ ); + if ( whatIWant > recievedPower ) + accepted = (float) recievedPower; + else + accepted = (float) whatIWant; + } + + return accepted; + } + + @Override + final public float getRequest(ForgeDirection direction) + { + return (float) getExternalPowerDemand( PowerUnits.KJ ); + } + + @Override + final public float getVoltage() + { + return 120; + } + + @Override + final public ElectricityPack provideElectricity(ForgeDirection from, ElectricityPack request, boolean doProvide) + { + return null; // cannot be dis-charged + } + + @Override + final public float getProvide(ForgeDirection direction) + { + return 0; + } + +} +*/ \ No newline at end of file diff --git a/tile/qnb/TileQuantumBridge.java b/tile/qnb/TileQuantumBridge.java new file mode 100644 index 00000000..8655682e --- /dev/null +++ b/tile/qnb/TileQuantumBridge.java @@ -0,0 +1,111 @@ +package appeng.tile.qnb; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import appeng.api.AEApi; +import appeng.me.cluster.IAECluster; +import appeng.me.cluster.IAEMultiBlock; +import appeng.me.cluster.implementations.QuantumCluster; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; + +public class TileQuantumBridge extends AENetworkPowerTile implements IAEMultiBlock +{ + + final int sidesRing[] = new int[] {}; + final int sidesLink[] = new int[] { 0 }; + + AppEngInternalInventory inv = new AppEngInternalInventory( this, 1 ); + + final byte start = 8 + 7; + public final byte corner = 16; + final byte hasSingularity = 32; + final byte powered = 64; + + // private QuantumCalculator calc = new QuantumCalculator( this ); + int oldxdex = -1; + byte xdex = -1; + + QuantumCluster clust; + public boolean bridgePowered; + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + if ( isCenter() ) + return sidesLink; + return sidesRing; + } + + @Override + public void disconnect() + { + // TODO Auto-generated method stub + + } + + @Override + public IAECluster getCluster() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isValid() + { + // TODO Auto-generated method stub + return false; + } + + public void updateStatus(QuantumCluster c, byte fish) + { + // TODO Auto-generated method stub + + } + + public long getQEDest() + { + // TODO Auto-generated method stub + return 0; + } + + public boolean isCenter() + { + return getBlockType() == AEApi.instance().blocks().blockQuantumLink.block(); + } + + public boolean isCorner() + { + // TODO Auto-generated method stub + return false; + } + + public boolean isPowered() + { + if ( Platform.isClient() ) + return (xdex & powered) == powered; + + return false; + } + + public boolean isFormed() + { + return xdex != -1; + } + +} diff --git a/tile/spatial/TileSpatialIOPort.java b/tile/spatial/TileSpatialIOPort.java new file mode 100644 index 00000000..45e0e0ba --- /dev/null +++ b/tile/spatial/TileSpatialIOPort.java @@ -0,0 +1,68 @@ +package appeng.tile.spatial; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileSpatialIOPort extends AENetworkInvTile +{ + + final int sides[] = { 0, 1 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 ); + boolean lastRedstoneState = false; + + public void updateRedstoneState() + { + boolean currentState = worldObj.isBlockIndirectlyGettingPowered( xCoord, yCoord, zCoord ); + if ( lastRedstoneState != currentState ) + { + lastRedstoneState = currentState; + if ( currentState ) + { + triggerTransition(); + } + } + } + + private void triggerTransition() + { + // TODO Auto-generated method stub + + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + +} diff --git a/tile/spatial/TileSpatialPylon.java b/tile/spatial/TileSpatialPylon.java new file mode 100644 index 00000000..3f010056 --- /dev/null +++ b/tile/spatial/TileSpatialPylon.java @@ -0,0 +1,229 @@ +package appeng.tile.spatial; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.GridFlags; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.me.GridAccessException; +import appeng.me.cluster.IAEMultiBlock; +import appeng.me.cluster.implementations.SpatialPylonCalculator; +import appeng.me.cluster.implementations.SpatialPylonCluster; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.AENetworkProxyMultiblock; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkTile; + +public class TileSpatialPylon extends AENetworkTile implements IAEMultiBlock +{ + + public final int DISPLAY_ENDMIN = 0x01; + public final int DISPLAY_ENDMAX = 0x02; + public final int DISPLAY_MIDDLE = 0x01 + 0x02; + public final int DISPLAY_X = 0x04; + public final int DISPLAY_Y = 0x08; + public final int DISPLAY_Z = 0x04 + 0x08; + public final int MB_STATUS = 0x01 + 0x02 + 0x04 + 0x08; + + public final int DISPLAY_ENABLED = 0x10; + public final int DISPLAY_POWEREDENABLED = 0x20; + public final int NET_STATUS = 0x10 + 0x20; + + int displayBits = 0; + SpatialPylonCluster clust; + final SpatialPylonCalculator calc = new SpatialPylonCalculator( this ); + + boolean didHaveLight = false; + + @Override + protected AENetworkProxy createProxy() + { + return new AENetworkProxyMultiblock( this, "proxy", true ); + } + + @Override + public boolean canBeRotated() + { + return false; + } + + private class TileSpatialPylonHandler extends AETileEventHandler + { + + public TileSpatialPylonHandler() { + super( EnumSet.of( TileEventType.NETWORK ) ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + int old = displayBits; + displayBits = data.readByte(); + return old != displayBits; + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + data.writeByte( displayBits ); + } + + }; + + public TileSpatialPylon() { + gridProxy.setFlags( GridFlags.REQURE_CHANNEL, GridFlags.MULTIBLOCK ); + gridProxy.setIdlePowerUsage( 0.5 ); + gridProxy.setValidSides( EnumSet.noneOf( ForgeDirection.class ) ); + addNewHandler( new TileSpatialPylonHandler() ); + } + + @Override + public void onReady() + { + super.onReady(); + onNeighborBlockChange(); + } + + @Override + public void markForUpdate() + { + super.markForUpdate(); + boolean hasLight = getLightValue() > 0; + if ( hasLight != didHaveLight ) + { + didHaveLight = hasLight; + worldObj.updateAllLightTypes( xCoord, yCoord, zCoord ); + } + } + + public int getLightValue() + { + if ( (displayBits & DISPLAY_POWEREDENABLED) == DISPLAY_POWEREDENABLED ) + { + return 8; + } + return 0; + } + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + recalculateDisplay(); + } + + @MENetworkEventSubscribe + public void activeRender(MENetworkChannelsChanged c) + { + recalculateDisplay(); + } + + @Override + public void invalidate() + { + super.invalidate(); + disconnect(); + } + + @Override + public void onChunkUnload() + { + super.onChunkUnload(); + disconnect(); + } + + public void onNeighborBlockChange() + { + calc.calculateMultiblock( worldObj, getLocation() ); + } + + @Override + public SpatialPylonCluster getCluster() + { + return clust; + } + + public void recalculateDisplay() + { + int oldBits = displayBits; + + displayBits = 0; + + if ( clust != null ) + { + if ( clust.min.equals( getLocation() ) ) + displayBits = DISPLAY_ENDMIN; + else if ( clust.max.equals( getLocation() ) ) + displayBits = DISPLAY_ENDMAX; + else + displayBits = DISPLAY_MIDDLE; + + switch (clust.currentAxis) + { + case X: + displayBits |= DISPLAY_X; + break; + case Y: + displayBits |= DISPLAY_Y; + break; + case Z: + displayBits |= DISPLAY_Z; + break; + default: + displayBits = 0; + break; + } + + try + { + if ( gridProxy.getEnergy().isNetworkPowered() ) + displayBits |= DISPLAY_POWEREDENABLED; + + if ( clust.isValid && gridProxy.isActive() ) + displayBits |= DISPLAY_ENABLED; + } + catch (GridAccessException e) + { + // nothing? + } + + } + + if ( oldBits != displayBits ) + markForUpdate(); + } + + public void updateStatus(SpatialPylonCluster c) + { + clust = c; + gridProxy.setValidSides( c == null ? EnumSet.noneOf( ForgeDirection.class ) : EnumSet.allOf( ForgeDirection.class ) ); + recalculateDisplay(); + } + + @Override + public void disconnect() + { + if ( clust != null ) + { + clust.destroy(); + updateStatus( null ); + } + } + + @Override + public boolean isValid() + { + return true; + } + + public int getDisplayBits() + { + return displayBits; + } + +} diff --git a/tile/storage/TileChest.java b/tile/storage/TileChest.java new file mode 100644 index 00000000..919fcb09 --- /dev/null +++ b/tile/storage/TileChest.java @@ -0,0 +1,620 @@ +package appeng.tile.storage; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.implementations.IMEChest; +import appeng.api.networking.GridFlags; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.events.MENetworkPowerStorage; +import appeng.api.networking.events.MENetworkPowerStorage.PowerEventType; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMontorHandlerReciever; +import appeng.api.storage.MEMontorHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; +import appeng.core.AELog; +import appeng.helpers.AENoHandler; +import appeng.me.GridAccessException; +import appeng.me.storage.MEInventoryHandler; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkPowerTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; +import appeng.util.item.AEFluidStack; + +public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHandler +{ + + static final AENoHandler noHandler = new AENoHandler(); + + static final int sides[] = new int[] { 0 }; + static final int front[] = new int[] { 1 }; + + AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 ); + + ItemStack storageType; + long lastStateChange = 0; + int priority = 0; + int state = 0; + + private void recalculateDisplay() + { + int oldState = state; + + for (int x = 0; x < getCellCount(); x++) + state |= (getCellStatus( x ) << (3 * x)); + + if ( getAECurrentPower() > 64 || gridProxy.isActive() ) + state |= 0x40; + else + state &= ~0x40; + + if ( oldState != state ) + markForUpdate(); + } + + @Override + protected void PowerEvent(PowerEventType x) + { + if ( x == PowerEventType.REQUEST_POWER ) + { + try + { + gridProxy.getGrid().postEvent( new MENetworkPowerStorage( this, PowerEventType.REQUEST_POWER ) ); + } + catch (GridAccessException e) + { + // :( + } + } + else + recalculateDisplay(); + } + + private class invManger extends AETileEventHandler + { + + public invManger() { + super( EnumSet.of( TileEventType.TICK, TileEventType.NETWORK, TileEventType.WORLD_NBT ) ); + } + + @Override + public void Tick() + { + if ( Platform.isClient() ) + return; + + double idleUsage = gridProxy.getIdlePowerUsage(); + + try + { + if ( !gridProxy.getEnergy().isNetworkPowered() ) + { + double powerUsed = extractAEPower( idleUsage, Actionable.MODULATE, PowerMultiplier.CONFIG ); // drain + if ( powerUsed + 0.1 >= idleUsage != (state & 0x40) > 0 ) + recalculateDisplay(); + } + } + catch (GridAccessException e) + { + double powerUsed = extractAEPower( gridProxy.getIdlePowerUsage(), Actionable.MODULATE, PowerMultiplier.CONFIG ); // drain + if ( powerUsed + 0.1 >= idleUsage != (state & 0x40) > 0 ) + recalculateDisplay(); + } + + if ( inv.getStackInSlot( 0 ) != null ) + { + tryToStoreContents(); + } + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + if ( worldObj.getTotalWorldTime() - lastStateChange > 8 ) + state = 0; + else + state &= 0x24924924; // just keep the blinks... + + for (int x = 0; x < getCellCount(); x++) + state |= (getCellStatus( x ) << (3 * x)); + + if ( getAECurrentPower() > 64 || gridProxy.isActive() ) + state |= 0x40; + else + state &= ~0x40; + + data.writeByte( state ); + ItemStack is = inv.getStackInSlot( 1 ); + + if ( is == null ) + { + data.writeInt( 0 ); + } + else + { + data.writeInt( (is.getItemDamage() << Platform.DEF_OFFSET) | is.itemID ); + } + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + int oldState = state; + ItemStack oldType = storageType; + + state = data.readByte(); + + int item = data.readInt(); + + if ( item == 0 ) + storageType = null; + else + storageType = new ItemStack( item & 0xffff, 1, item >> Platform.DEF_OFFSET ); + + lastStateChange = worldObj.getTotalWorldTime(); + + AELog.info( "" + (state & 0x40) ); + return (state & 0xDB6DB6DB) != (oldState & 0xDB6DB6DB) || oldType != storageType; + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + priority = data.getInteger( "priority" ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setInteger( "priority", priority ); + } + + }; + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + recalculateDisplay(); + } + + @MENetworkEventSubscribe + public void channelRender(MENetworkChannelsChanged c) + { + recalculateDisplay(); + } + + public TileChest() { + gridProxy.setFlags( GridFlags.REQURE_CHANNEL ); + addNewHandler( new invManger() ); + + internalPublicPowerStorage = true; + internalPowerFlow = AccessRestriction.WRITE; + } + + boolean isCached = false; + + private ICellHandler cellHandler; + private MEMontorHandler icell; + private MEMontorHandler fcell; + + @Override + public IMEMonitor getItemInventory() + { + return icell; + } + + @Override + public IMEMonitor getFluidInventory() + { + return fcell; + } + + class ChestNetNotifier> implements IMEMontorHandlerReciever + { + + final StorageChannel chan; + + public ChestNetNotifier(StorageChannel chan) { + this.chan = chan; + } + + @Override + public void postChange(T change) + { + try + { + gridProxy.getStorage().postAlterationOfStoredItems( chan, change ); + } + catch (GridAccessException e) + { + // :( + } + } + + @Override + public boolean isValid(Object verificationToken) + { + if ( chan == StorageChannel.ITEMS ) + return verificationToken == icell; + if ( chan == StorageChannel.FLUIDS ) + return verificationToken == fcell; + return false; + } + + }; + + private MEMontorHandler wrap(IMEInventoryHandler h) + { + if ( h == null ) + return null; + + MEInventoryHandler ih = new MEInventoryHandler( h ); + ih.myPriority = priority; + + MEMontorHandler g = new MEMontorHandler( ih ); + g.addListener( new ChestNetNotifier( h.getChannel() ), g ); + + return g; + } + + private IMEInventoryHandler getHandler(StorageChannel channel) throws AENoHandler + { + if ( !isCached ) + { + ItemStack is = inv.getStackInSlot( 1 ); + if ( is != null ) + { + isCached = true; + cellHandler = AEApi.instance().registries().cell().getHander( is ); + icell = wrap( cellHandler.getCellInventory( is, StorageChannel.ITEMS ) ); + fcell = wrap( cellHandler.getCellInventory( is, StorageChannel.FLUIDS ) ); + } + } + + switch (channel) + { + case FLUIDS: + if ( fcell == null ) + throw noHandler; + return fcell; + case ITEMS: + if ( icell == null ) + throw noHandler; + return icell; + default: + } + + return null; + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + if ( slot == 1 ) + { + icell = null; + fcell = null; + isCached = false; // recalculate the storage cell. + + try + { + IStorageGrid gs = gridProxy.getStorage(); + Platform.postChanges( gs, removed, added ); + + gridProxy.getGrid().postEvent( new MENetworkCellArrayUpdate() ); + } + catch (GridAccessException e) + { + + } + + // update the neighbors + if ( worldObj != null ) + { + worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, 0 ); + markForUpdate(); + } + } + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemstack) + { + inv.setInventorySlotContents( i, itemstack ); + tryToStoreContents(); + } + + private void tryToStoreContents() + { + try + { + if ( getStackInSlot( 0 ) != null ) + { + IMEInventory cell = getHandler( StorageChannel.ITEMS ); + + IAEItemStack returns = Platform.poweredInsert( this, cell, AEApi.instance().storage().createItemStack( inv.getStackInSlot( 0 ) ) ); + + if ( returns == null ) + inv.setInventorySlotContents( 0, null ); + else + inv.setInventorySlotContents( 0, returns.getItemStack() ); + } + } + catch (AENoHandler t) + { + } + } + + @Override + public boolean canExtractItem(int i, ItemStack itemstack, int j) + { + return false; + } + + @Override + public boolean canInsertItem(int i, ItemStack itemstack, int j) + { + try + { + IMEInventory cell = getHandler( StorageChannel.ITEMS ); + IAEItemStack returns = cell.injectItems( AEApi.instance().storage().createItemStack( inv.getStackInSlot( 0 ) ), Actionable.SIMULATE ); + return returns == null || returns.getStackSize() != itemstack.stackSize; + } + catch (AENoHandler t) + { + } + + return false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + if ( side == getForward().ordinal() ) + return front; + return sides; + } + + @Override + public List getCellArray(StorageChannel channel) + { + try + { + return Arrays.asList( new IMEInventoryHandler[] { getHandler( channel ) } ); + } + catch (AENoHandler e) + { + return new ArrayList(); + } + } + + @Override + public int getPriority() + { + return priority; + } + + @Override + public int getCellCount() + { + return 1; + } + + @Override + public void blinkCell(int slot) + { + long now = worldObj.getTotalWorldTime(); + if ( now - lastStateChange > 8 ) + state = 0; + lastStateChange = now; + + state |= 1 << (slot * 3 + 2); + } + + @Override + public boolean isCellBlinking(int slot) + { + long now = worldObj.getTotalWorldTime(); + if ( now - lastStateChange > 8 ) + return false; + + return ((state >> (slot * 3 + 2)) & 0x01) == 0x01; + } + + @Override + public int getCellStatus(int slot) + { + if ( Platform.isClient() ) + return (state >> (slot * 3)) & 3; + + ItemStack cell = inv.getStackInSlot( 1 ); + ICellHandler ch = AEApi.instance().registries().cell().getHander( cell ); + + if ( ch != null ) + { + try + { + IMEInventoryHandler handler = getHandler( StorageChannel.ITEMS ); + if ( ch != null ) + return ch.getStatusForCell( cell, handler ); + } + catch (AENoHandler e) + { + } + + try + { + IMEInventoryHandler handler = getHandler( StorageChannel.FLUIDS ); + if ( ch != null ) + return ch.getStatusForCell( cell, handler ); + } + catch (AENoHandler e) + { + } + } + + return 0; + } + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) + { + double req = resource.amount / 500.0; + double available = extractAEPower( req, Actionable.SIMULATE, PowerMultiplier.CONFIG ); + if ( available >= req - 0.01 ) + { + try + { + IMEInventoryHandler h = getHandler( StorageChannel.FLUIDS ); + + extractAEPower( req, Actionable.MODULATE, PowerMultiplier.CONFIG ); + IAEStack results = h.injectItems( AEFluidStack.create( resource ), doFill ? Actionable.MODULATE : Actionable.SIMULATE ); + + if ( results == null ) + return resource.amount; + + return resource.amount - (int) results.getStackSize(); + } + catch (AENoHandler e) + { + } + } + return 0; + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) + { + return null; + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) + { + return null; + } + + @Override + public boolean canFill(ForgeDirection from, Fluid fluid) + { + try + { + IMEInventoryHandler h = getHandler( StorageChannel.FLUIDS ); + return h.canAccept( AEFluidStack.create( new FluidStack( fluid, 1 ) ) ); + } + catch (AENoHandler e) + { + } + return false; + } + + @Override + public boolean canDrain(ForgeDirection from, Fluid fluid) + { + return false; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) + { + try + { + IMEInventoryHandler h = getHandler( StorageChannel.FLUIDS ); + if ( h.getChannel() == StorageChannel.FLUIDS ) + return new FluidTankInfo[] { new FluidTankInfo( null ) }; // eh? + } + catch (AENoHandler e) + { + } + + return null; + } + + @Override + protected double extractAEPower(double amt, Actionable mode) + { + double stash = 0.0; + + IEnergyGrid eg; + try + { + eg = gridProxy.getEnergy(); + stash = eg.extractAEPower( amt, mode, PowerMultiplier.ONE ); + if ( stash >= amt ) + return stash; + } + catch (GridAccessException e) + { + // no grid :( + } + + // local battery! + return super.extractAEPower( amt - stash, mode ) + stash; + } + + @Override + public boolean isPowered() + { + if ( Platform.isClient() ) + return (state & 0x40) == 0x40; + + boolean gridPowered = getAECurrentPower() > 64; + + if ( !gridPowered ) + { + try + { + gridPowered = gridProxy.getEnergy().isNetworkPowered(); + } + catch (GridAccessException e) + { + } + } + + return super.getAECurrentPower() > 1 || gridPowered; + } + + public ItemStack getStorageType() + { + if ( isPowered() ) + return storageType; + return null; + } + +} diff --git a/tile/storage/TileDrive.java b/tile/storage/TileDrive.java new file mode 100644 index 00000000..e3d949d5 --- /dev/null +++ b/tile/storage/TileDrive.java @@ -0,0 +1,303 @@ +package appeng.tile.storage; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.AEApi; +import appeng.api.implementations.IChestOrDrive; +import appeng.api.networking.GridFlags; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.me.GridAccessException; +import appeng.me.storage.MEInventoryHandler; +import appeng.tile.events.AETileEventHandler; +import appeng.tile.events.TileEventType; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; + +public class TileDrive extends AENetworkInvTile implements IChestOrDrive +{ + + final int sides[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 10 ); + + boolean isCached = false; + ICellHandler handlersBySlot[] = new ICellHandler[10]; + IMEInventoryHandler invBySlot[] = new IMEInventoryHandler[10]; + List items = new LinkedList(); + List fluids = new LinkedList(); + + long lastStateChange = 0; + int state = 0; + int priority = 0; + + private void recalculateDisplay() + { + int oldState = 0; + + if ( gridProxy.isActive() ) + state |= 0x80000000; + else + state &= ~0x80000000; + + for (int x = 0; x < getCellCount(); x++) + state |= (getCellStatus( x ) << (3 * x)); + + if ( oldState != state ) + markForUpdate(); + } + + private class invManger extends AETileEventHandler + { + + public invManger() { + super( EnumSet.of( TileEventType.WORLD_NBT, TileEventType.NETWORK ) ); + } + + @Override + public void writeToStream(DataOutputStream data) throws IOException + { + if ( worldObj.getTotalWorldTime() - lastStateChange > 8 ) + state = 0; + else + state &= 0x24924924; // just keep the blinks... + + if ( gridProxy.isActive() ) + state |= 0x80000000; + else + state &= ~0x80000000; + + for (int x = 0; x < getCellCount(); x++) + state |= (getCellStatus( x ) << (3 * x)); + + data.writeInt( state ); + } + + @Override + public boolean readFromStream(DataInputStream data) throws IOException + { + int oldState = state; + state = data.readInt(); + lastStateChange = worldObj.getTotalWorldTime(); + return (state & 0xDB6DB6DB) != (oldState & 0xDB6DB6DB); + } + + @Override + public void readFromNBT(NBTTagCompound data) + { + priority = data.getInteger( "priority" ); + } + + @Override + public void writeToNBT(NBTTagCompound data) + { + data.setInteger( "priority", priority ); + } + + }; + + @MENetworkEventSubscribe + public void powerRender(MENetworkPowerStatusChange c) + { + recalculateDisplay(); + } + + @MENetworkEventSubscribe + public void channelRender(MENetworkChannelsChanged c) + { + recalculateDisplay(); + } + + public TileDrive() { + gridProxy.setFlags( GridFlags.REQURE_CHANNEL ); + addNewHandler( new invManger() ); + } + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + isCached = false; // recalculate the storage cell. + updateState(); + + try + { + IStorageGrid gs = gridProxy.getStorage(); + Platform.postChanges( gs, removed, added ); + + gridProxy.getGrid().postEvent( new MENetworkCellArrayUpdate() ); + } + catch (GridAccessException e) + { + } + + markForUpdate(); + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + + public void updateState() + { + if ( !isCached ) + { + items = new LinkedList(); + fluids = new LinkedList(); + + for (int x = 0; x < inv.getSizeInventory(); x++) + { + ItemStack is = inv.getStackInSlot( x ); + invBySlot[x] = null; + handlersBySlot[x] = null; + + if ( is != null ) + { + handlersBySlot[x] = AEApi.instance().registries().cell().getHander( is ); + + if ( handlersBySlot[x] != null ) + { + IMEInventoryHandler cell = handlersBySlot[x].getCellInventory( is, StorageChannel.ITEMS ); + + if ( cell != null ) + { + MEInventoryHandler ih = new MEInventoryHandler( cell ); + ih.myPriority = priority; + invBySlot[x] = ih; + items.add( ih ); + } + else + { + cell = handlersBySlot[x].getCellInventory( is, StorageChannel.FLUIDS ); + + if ( cell != null ) + { + MEInventoryHandler ih = new MEInventoryHandler( cell ); + ih.myPriority = priority; + invBySlot[x] = ih; + fluids.add( ih ); + } + } + } + } + } + + isCached = true; + } + } + + @Override + public List getCellArray(StorageChannel channel) + { + updateState(); + return (List) (channel == StorageChannel.ITEMS ? items : fluids); + } + + @Override + public int getPriority() + { + return priority; + } + + @Override + public int getCellCount() + { + return 10; + } + + @Override + public void blinkCell(int slot) + { + long now = worldObj.getTotalWorldTime(); + if ( now - lastStateChange > 8 ) + state = 0; + lastStateChange = now; + + state |= 1 << (slot * 3 + 2); + } + + @Override + public boolean isCellBlinking(int slot) + { + long now = worldObj.getTotalWorldTime(); + if ( now - lastStateChange > 8 ) + return false; + + return ((state >> (slot * 3 + 2)) & 0x01) == 0x01; + } + + @Override + public int getCellStatus(int slot) + { + if ( Platform.isClient() ) + return (state >> (slot * 3)) & 3; + + ItemStack cell = inv.getStackInSlot( 2 ); + ICellHandler ch = handlersBySlot[slot]; + + IMEInventoryHandler handler = invBySlot[slot]; + if ( handler == null ) + return 0; + + if ( handler.getChannel() == StorageChannel.ITEMS ) + { + if ( ch != null ) + return ch.getStatusForCell( cell, handler ); + } + + if ( handler.getChannel() == StorageChannel.FLUIDS ) + { + if ( ch != null ) + return ch.getStatusForCell( cell, handler ); + } + + return 0; + } + + @Override + public boolean isPowered() + { + if ( Platform.isClient() ) + return (state & 0x80000000) == 0x80000000; + + return gridProxy.isActive(); + } + +} diff --git a/tile/storage/TileIOPort.java b/tile/storage/TileIOPort.java new file mode 100644 index 00000000..1b504b74 --- /dev/null +++ b/tile/storage/TileIOPort.java @@ -0,0 +1,48 @@ +package appeng.tile.storage; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.util.AECableType; +import appeng.api.util.DimensionalCoord; +import appeng.tile.grid.AENetworkInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; + +public class TileIOPort extends AENetworkInvTile +{ + + final int sides[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + AppEngInternalInventory inv = new AppEngInternalInventory( this, 12 ); + + @Override + public AECableType getCableConnectionType(ForgeDirection dir) + { + return AECableType.SMART; + } + + @Override + public DimensionalCoord getLocation() + { + return new DimensionalCoord( this ); + } + + @Override + public IInventory getInternalInventory() + { + return inv; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) + { + // TODO Auto-generated method stub + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + return sides; + } + +} diff --git a/util/ConfigManager.java b/util/ConfigManager.java new file mode 100644 index 00000000..58c50c0d --- /dev/null +++ b/util/ConfigManager.java @@ -0,0 +1,87 @@ +package appeng.util; + +import java.util.HashMap; +import java.util.Set; + +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.util.IConfigManager; + +public class ConfigManager implements IConfigManager +{ + + HashMap Settings = new HashMap(); + IConfigManagerHost target; + + public ConfigManager(IConfigManagerHost tile) { + target = tile; + } + + /** + * read all settings using config manager. + * + * @param tagCompound + */ + @SuppressWarnings("static-access") + @Override + public void readFromNBT(NBTTagCompound tagCompound) + { + for (Enum key : Settings.keySet()) + { + String value = tagCompound.getString( key.name() ); + + Enum oldValue = Settings.get( key ); + Enum newValue = oldValue.valueOf( oldValue.getClass(), value ); + + putSetting( key, newValue ); + } + } + + /** + * save all settings using config manager. + * + * @param tagCompound + */ + @Override + public void writeToNBT(NBTTagCompound tagCompound) + { + + for (Enum e : Settings.keySet()) + { + tagCompound.setString( e.name(), e.name() ); + } + + } + + @Override + public Set getSettings() + { + return Settings.keySet(); + } + + @Override + public void registerSetting(Enum settingName, Enum defaultValue) + { + Settings.put( settingName, defaultValue ); + } + + @Override + public Enum getSetting(Enum settingName) + { + Enum oldValue = Settings.get( settingName ); + + if ( oldValue != null ) + return oldValue; + + throw new RuntimeException( "Invalid Config setting" ); + } + + @Override + public Enum putSetting(Enum settingName, Enum newValue) + { + Enum oldValue = getSetting( settingName ); + Settings.put( settingName, newValue ); + target.updateSetting( settingName, newValue ); + return oldValue; + } + +} diff --git a/util/IConfigManagerHost.java b/util/IConfigManagerHost.java new file mode 100644 index 00000000..6ffc6a0a --- /dev/null +++ b/util/IConfigManagerHost.java @@ -0,0 +1,7 @@ +package appeng.util; + +public interface IConfigManagerHost { + + void updateSetting(Enum settingName, Enum newValue); + +} diff --git a/util/InWorldToolOperationResult.java b/util/InWorldToolOperationResult.java new file mode 100644 index 00000000..9f0c7599 --- /dev/null +++ b/util/InWorldToolOperationResult.java @@ -0,0 +1,56 @@ +package appeng.util; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; + +public class InWorldToolOperationResult +{ + + public ItemStack BlockItem; + public List Drops; + + public static InWorldToolOperationResult getBlockOperationResult(ItemStack[] items) + { + List temp = new ArrayList(); + ItemStack b = null; + + for (ItemStack l : items) + { + if ( b == null ) + { + if ( Block.blocksList.length > l.itemID ) + { + Block bl = Block.blocksList[l.itemID]; + + if ( bl.blockID > 0 ) + { + b = l; + continue; + } + } + } + + temp.add( l ); + } + + return new InWorldToolOperationResult( b, temp ); + } + + public InWorldToolOperationResult() { + BlockItem = null; + Drops = null; + } + + public InWorldToolOperationResult(ItemStack block, List drops) { + BlockItem = block; + Drops = drops; + } + + public InWorldToolOperationResult(ItemStack block) { + BlockItem = block; + Drops = null; + } +} diff --git a/util/InventoryAdaptor.java b/util/InventoryAdaptor.java new file mode 100644 index 00000000..7a4cbedc --- /dev/null +++ b/util/InventoryAdaptor.java @@ -0,0 +1,98 @@ +package appeng.util; + +import java.util.ArrayList; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.FuzzyMode; +import appeng.integration.modules.BS; +import appeng.util.inv.AdaptorIInventory; +import appeng.util.inv.AdaptorISpecialInventory; +import appeng.util.inv.AdaptorList; +import appeng.util.inv.AdaptorPlayerInventory; +import appeng.util.inv.IInventoryDestination; +import appeng.util.inv.ItemSlot; +import appeng.util.inv.WrapperMCISidedInventory; +import buildcraft.api.inventory.ISpecialInventory; +import cpw.mods.fml.common.network.Player; + +public abstract class InventoryAdaptor implements Iterable +{ + + // return what was extracted. + public abstract ItemStack removeItems(int how_many, ItemStack Filter, IInventoryDestination destination); + + public abstract ItemStack simulateRemove(int how_many, ItemStack Filter, IInventoryDestination destination); + + // return what was extracted. + public abstract ItemStack removeSimilarItems(int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination); + + public abstract ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination); + + // return what isn't used... + public abstract ItemStack addItems(ItemStack A); + + public abstract ItemStack simulateAdd(ItemStack A); + + public abstract boolean containsItems(); + + // returns an appropriate adaptor, or null + public static InventoryAdaptor getAdaptor(Object te, ForgeDirection d) + { + if ( te == null ) + return null; + + if ( te instanceof Player ) + { + return new AdaptorIInventory( new AdaptorPlayerInventory( ((EntityPlayer) te).inventory ) ); + } + else if ( te instanceof ArrayList ) + { + return new AdaptorList( (ArrayList) te ); + } + else if ( BS.instance != null && BS.instance.isStorageCrate( te ) ) + { + return BS.instance.getAdaptor( te, d ); + } + else if ( te instanceof TileEntityChest ) + { + return new AdaptorIInventory( (IInventory) Platform.GetChestInv( te ) ); + } + else if ( isSpecialInventory( te ) ) + { + return new AdaptorISpecialInventory( (ISpecialInventory) te, d ); + } + else if ( te instanceof ISidedInventory ) + { + return new AdaptorIInventory( new WrapperMCISidedInventory( (ISidedInventory) te, d ) ); + } + else if ( te instanceof IInventory ) + { + return new AdaptorIInventory( (IInventory) te ); + } + + return null; + } + + private static boolean canBeSpecial = true; + + private static boolean isSpecialInventory(Object a) + { + if ( canBeSpecial ) + { + try + { + return a instanceof ISpecialInventory; + } + catch (Throwable e) + { + canBeSpecial = false; + } + } + return false; + } +} diff --git a/util/ItemSorters.java b/util/ItemSorters.java new file mode 100644 index 00000000..a10ee8d4 --- /dev/null +++ b/util/ItemSorters.java @@ -0,0 +1,84 @@ +package appeng.util; + +import java.util.Comparator; + +import appeng.api.config.SortDir; +import appeng.api.storage.data.IAEItemStack; + +public class ItemSorters +{ + + public static SortDir Direction = SortDir.ASCENDING; + + public static int compareInt(int a, int b) + { + if ( a == b ) + return 0; + if ( a < b ) + return -1; + return 1; + } + + public static int compareLong(long a, long b) + { + if ( a == b ) + return 0; + if ( a < b ) + return -1; + return 1; + } + + public static Comparator ConfigBased_SortByName = new Comparator() { + + @Override + public int compare(IAEItemStack o1, IAEItemStack o2) + { + if ( Direction == SortDir.ASCENDING ) + return Platform.getItemDisplayName( o1 ).toLowerCase().compareTo( Platform.getItemDisplayName( o2 ).toLowerCase() ); + return Platform.getItemDisplayName( o2 ).toLowerCase().compareTo( Platform.getItemDisplayName( o1 ).toLowerCase() ); + } + }; + + public static Comparator ConfigBased_SortByID = new Comparator() { + + @Override + public int compare(IAEItemStack o1, IAEItemStack o2) + { + if ( Direction == SortDir.ASCENDING ) + { + int comp = compareInt( o1.getItem().itemID, o2.getItem().itemID ); + if ( comp == 0 ) + comp = compareInt( o1.getItemDamage(), o2.getItemDamage() ); + return comp; + } + + int comp = -compareInt( o1.getItem().itemID, o2.getItem().itemID ); + if ( comp == 0 ) + comp = -compareInt( o1.getItemDamage(), o2.getItemDamage() ); + return comp; + } + }; + + public static Comparator ConfigBased_SortByMod = new Comparator() { + + @Override + public int compare(IAEItemStack o1, IAEItemStack o2) + { + if ( Direction == SortDir.ASCENDING ) + return Platform.getMod( o1.getItemStack() ).compareTo( Platform.getMod( o2.getItemStack() ) ); + return Platform.getMod( o2.getItemStack() ).compareTo( Platform.getMod( o1.getItemStack() ) ); + } + }; + + public static Comparator ConfigBased_SortBySize = new Comparator() { + + @Override + public int compare(IAEItemStack o1, IAEItemStack o2) + { + if ( Direction == SortDir.ASCENDING ) + return compareLong( o2.getStackSize(), o1.getStackSize() ); + return compareLong( o1.getStackSize(), o2.getStackSize() ); + } + }; + +} diff --git a/util/LookDirection.java b/util/LookDirection.java new file mode 100644 index 00000000..e496261d --- /dev/null +++ b/util/LookDirection.java @@ -0,0 +1,15 @@ +package appeng.util; + +import net.minecraft.util.Vec3; + +public class LookDirection +{ + + public final Vec3 a; + public final Vec3 b; + + public LookDirection(Vec3 a, Vec3 b) { + this.a = a; + this.b = b; + } +} diff --git a/util/Platform.java b/util/Platform.java new file mode 100644 index 00000000..37244512 --- /dev/null +++ b/util/Platform.java @@ -0,0 +1,1250 @@ +package appeng.util; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.WeakHashMap; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.IInventory; +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.NBTTagByte; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagDouble; +import net.minecraft.nbt.NBTTagFloat; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagString; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.util.MathHelper; +import net.minecraft.util.StatCollector; +import net.minecraft.util.Vec3; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.FakePlayer; +import net.minecraftforge.common.ForgeDirection; +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.implementations.IAEItemPowerStorage; +import appeng.api.implementations.IAEWrench; +import appeng.api.networking.energy.IEnergySource; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEMontorHandlerReciever; +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.AEItemDefinition; +import appeng.core.AELog; +import appeng.core.AppEng; +import appeng.core.Configuration; +import appeng.core.sync.GuiBridge; +import appeng.server.AccessType; +import appeng.server.Security; +import appeng.util.item.AEItemStack; +import appeng.util.item.AESharedNBT; +import appeng.util.item.ItemList; +import buildcraft.api.tools.IToolWrench; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableTable; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.registry.GameData; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class Platform +{ + + public static final int DEF_OFFSET = 16; + + /* + * random source, use it for item drop locations... + */ + static private Random rdnSrc = new Random(); + + public static int getRandomInt() + { + return Math.abs( rdnSrc.nextInt() ); + } + + public static float getRandomFloat() + { + return rdnSrc.nextFloat(); + } + + private static HashMap modIDToName; + private static HashMap itemTomodID; + + public static String getMod(String modID) + { + String out = modIDToName.get( modID ); + + if ( out == null ) + { + out = modID; + } + + return out; + } + + public static String getMod(ItemStack is) + { + if ( itemTomodID == null ) + { + itemTomodID = new HashMap(); + ImmutableTable modObjectTable; + + for (Field f : Block.class.getDeclaredFields()) + { + try + { + Object o = f.get( Block.class ); + if ( o instanceof Block ) + { + itemTomodID.put( ((Block) o).blockID, "minecraft" ); + } + } + catch (Throwable t) + { + } + } + + try + { + Field f = GameData.class.getDeclaredField( "modObjectTable" ); + f.setAccessible( true ); + modObjectTable = (ImmutableTable) f.get( GameData.class ); + f.setAccessible( false ); + + ImmutableMap> fish = modObjectTable.rowMap(); + for (Map g : fish.values()) + { + for (String key : g.keySet()) + itemTomodID.put( g.get( key ), key ); + } + } + catch (Throwable t) + { + } + } + + String out = itemTomodID.get( is.itemID ); + + if ( out == null ) + return "Unknown"; + + return out; + } + + public static ForgeDirection crossProduct(ForgeDirection forward, ForgeDirection up) + { + int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + switch (west_x + west_y * 2 + west_z * 3) + { + case 1: + return ForgeDirection.EAST; + case -1: + return ForgeDirection.WEST; + + case 2: + return ForgeDirection.UP; + case -2: + return ForgeDirection.DOWN; + + case 3: + return ForgeDirection.SOUTH; + case -3: + return ForgeDirection.NORTH; + } + + return ForgeDirection.UNKNOWN; + } + + /* + * Simple way to cycle an enum... + */ + public static T nextEnum(T ce) + { + EnumSet valList = EnumSet.allOf( ce.getClass() ); + + int pLoc = ce.ordinal() + 1; + if ( pLoc >= valList.size() ) + pLoc = 0; + + if ( pLoc < 0 || pLoc >= valList.size() ) + pLoc = 0; + + int pos = 0; + for (Object g : valList) + { + if ( pos++ == pLoc ) + return (T) g; + } + + return null; + } + + /* + * Simple way to cycle an enum... + */ + public static T prevEnum(T ce) + { + EnumSet valList = EnumSet.allOf( ce.getClass() ); + + int pLoc = ce.ordinal() - 1; + if ( pLoc < 0 ) + pLoc = valList.size() - 1; + + if ( pLoc < 0 || pLoc >= valList.size() ) + pLoc = 0; + + int pos = 0; + for (Object g : valList) + { + if ( pos++ == pLoc ) + return (T) g; + } + + return null; + } + + /* + * returns true if the code is on the client. + */ + public static boolean isClient() + { + return FMLCommonHandler.instance().getEffectiveSide().isClient(); + } + + /* + * returns true if the code is on the server. + */ + public static boolean isServer() + { + return FMLCommonHandler.instance().getEffectiveSide().isServer(); + } + + public static void openGUI(EntityPlayer p, TileEntity tile, ForgeDirection side, GuiBridge type) + { + if ( isClient() ) + return; + + if ( Security.hasPermissions( tile, p, AccessType.BLOCK_ACCESS ) ) + p.openGui( AppEng.instance, type.ordinal() << 3 | (side.ordinal()), tile.worldObj, tile.xCoord, tile.yCoord, tile.zCoord ); + } + + /* + * Checks to see if a block is air? + */ + public static boolean isBlockAir(World w, int x, int y, int z) + { + try + { + int bid = w.getBlockId( x, y, z ); + if ( bid <= 0 ) + return true; + if ( Block.blocksList[bid] == null ) + return true; + return Block.blocksList[bid].isAirBlock( w, x, y, z ); + } + catch (Throwable e) + { + return false; + } + } + + /* + * Lots of sillyness to try and account for weird tag related junk, basically requires that two tags have at least + * something in their tags before it wasts its time comparing them. + */ + public static boolean sameStackStags(ItemStack a, ItemStack b) + { + if ( a == null && b == null ) + return true; + if ( a == null || b == null ) + return false; + if ( a == b ) + return true; + + NBTTagCompound ta = a.getTagCompound(); + NBTTagCompound tb = b.getTagCompound(); + if ( ta == tb ) + return true; + + 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()) ) + return true; + + if ( (ta == null && tb != null) || (ta != null && tb == null) ) + return false; + + // if both tags are shared this is easy... + if ( AESharedNBT.isShared( ta ) && AESharedNBT.isShared( tb ) ) + { + return ta == tb; + } + + return NBTEqualityTest( ta, tb ); + } + + /* + * 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. + */ + public static boolean NBTEqualityTest(NBTBase A, NBTBase B) + { + // same type? + byte id = A.getId(); + if ( id == B.getId() ) + { + switch (id) + { + case 10: { + NBTTagCompound ctA = (NBTTagCompound) A; + NBTTagCompound ctB = (NBTTagCompound) B; + + Collection cA = ctA.getTags(); + Collection cB = ctB.getTags(); + + if ( cA.size() != cB.size() ) + return false; + + Iterator i = cA.iterator(); + while (i.hasNext()) + { + NBTBase tag = i.next(); + NBTBase aTag = ctB.getTag( tag.getName() ); + if ( aTag == null ) + return false; + + if ( !NBTEqualityTest( tag, aTag ) ) + return false; + } + + return true; + } + + case 9: // ) // A instanceof NBTTagList ) + { + NBTTagList lA = (NBTTagList) A; + NBTTagList lB = (NBTTagList) B; + if ( lA.tagCount() != lB.tagCount() ) + return false; + + for (int x = 0; x < lA.tagCount(); x++) + { + NBTBase tag = lA.tagAt( x ); + NBTBase aTag = lB.tagAt( x ); + + if ( aTag == null ) + return false; + + if ( !NBTEqualityTest( tag, aTag ) ) + return false; + } + + return true; + } + + case 1: // ( A instanceof NBTTagByte ) + return ((NBTTagByte) A).data == ((NBTTagByte) B).data; + + case 4: // else if ( A instanceof NBTTagLong ) + return ((NBTTagLong) A).data == ((NBTTagLong) B).data; + + case 8: // else if ( A instanceof NBTTagString ) + return ((NBTTagString) A).data == ((NBTTagString) B).data || ((NBTTagString) A).data.equals( ((NBTTagString) B).data ); + + case 6: // else if ( A instanceof NBTTagDouble ) + return ((NBTTagDouble) A).data == ((NBTTagDouble) B).data; + + case 5: // else if ( A instanceof NBTTagFloat ) + return ((NBTTagFloat) A).data == ((NBTTagFloat) B).data; + + case 3: // else if ( A instanceof NBTTagInt ) + return ((NBTTagInt) A).data == ((NBTTagInt) B).data; + + default: + return A.equals( B ); + } + } + + return false; + } + + /* + * Orderless hash on NBT Data, used to work thought huge piles fast, but ignroes the order just in case MC decided + * to change it... WHICH IS BAD... + */ + public static int NBTOrderlessHash(NBTBase A) + { + // same type? + int hash = 0; + byte id = A.getId(); + hash += id; + switch (id) + { + case 10: { + NBTTagCompound ctA = (NBTTagCompound) A; + + Collection cA = ctA.getTags(); + + Iterator i = cA.iterator(); + while (i.hasNext()) + { + NBTBase tag = i.next(); + hash += NBTOrderlessHash( ctA.getTag( tag.getName() ) ); + } + + return hash; + } + + case 9: // ) // A instanceof NBTTagList ) + { + NBTTagList lA = (NBTTagList) A; + hash += 9 * lA.tagCount(); + + for (int x = 0; x < lA.tagCount(); x++) + { + hash += NBTOrderlessHash( lA.tagAt( x ) ); + } + + return hash; + } + + case 1: // ( A instanceof NBTTagByte ) + return hash + ((NBTTagByte) A).data; + + case 4: // else if ( A instanceof NBTTagLong ) + return hash + (int) ((NBTTagLong) A).data; + + case 8: // else if ( A instanceof NBTTagString ) + return hash + ((NBTTagString) A).data.hashCode(); + + case 6: // else if ( A instanceof NBTTagDouble ) + return hash + (int) ((NBTTagDouble) A).data; + + case 5: // else if ( A instanceof NBTTagFloat ) + return hash + (int) ((NBTTagFloat) A).data; + + case 3: // else if ( A instanceof NBTTagInt ) + return hash + ((NBTTagInt) A).data; + + default: + return hash; + } + } + + /* + * The usual version of this returns an ItemStack, this version returns the recipe. + */ + public static IRecipe findMatchingRecipe(InventoryCrafting par1InventoryCrafting, World par2World) + { + CraftingManager cm = CraftingManager.getInstance(); + List rl = cm.getRecipeList(); + + for (int x = 0; x < rl.size(); ++x) + { + IRecipe r = rl.get( x ); + + if ( r.matches( par1InventoryCrafting, par2World ) ) + { + return r; + } + } + + return null; + } + + public static ItemStack[] getBlockDrops(World w, int x, int y, int z) + { + List out = new ArrayList(); + int bid = w.getBlockId( x, y, z ); + + if ( Block.blocksList.length > bid ) + { + Block which = Block.blocksList[bid]; + if ( which == null ) + return new ItemStack[0]; + out = which.getBlockDropped( w, x, y, z, w.getBlockMetadata( x, y, z ), 0 ); + } + + if ( out == null ) + return new ItemStack[0]; + return out.toArray( new ItemStack[out.size()] ); + } + + public static ForgeDirection cycleOrientations(ForgeDirection dir, boolean upAndDown) + { + if ( upAndDown ) + { + switch (dir) + { + case NORTH: + return ForgeDirection.SOUTH; + case SOUTH: + return ForgeDirection.EAST; + case EAST: + return ForgeDirection.WEST; + case WEST: + return ForgeDirection.NORTH; + case UP: + return ForgeDirection.UP; + case DOWN: + return ForgeDirection.DOWN; + case UNKNOWN: + return ForgeDirection.UNKNOWN; + } + } + else + { + switch (dir) + { + case UP: + return ForgeDirection.DOWN; + case DOWN: + return ForgeDirection.NORTH; + case NORTH: + return ForgeDirection.SOUTH; + case SOUTH: + return ForgeDirection.EAST; + case EAST: + return ForgeDirection.WEST; + case WEST: + return ForgeDirection.UP; + case UNKNOWN: + return ForgeDirection.UNKNOWN; + } + } + + return ForgeDirection.UNKNOWN; + } + + /* + * Creates / or loads previous NBT Data on items, used for editing items owned by AE. + */ + public static NBTTagCompound openNbtData(ItemStack i) + { + NBTTagCompound compound = i.getTagCompound(); + + if ( compound == null ) + { + i.setTagCompound( compound = new NBTTagCompound() ); + } + + return compound; + } + + /* + * Generates Item entiies in the world similar to how items are generally droped. + */ + public static void spawnDrops(World w, int x, int y, int z, List drops) + { + if ( isServer() ) + { + for (ItemStack i : drops) + { + if ( i != null ) + { + if ( i.stackSize > 0 ) + { + double offset_x = (getRandomInt() % 32 - 16) / 82; + double offset_y = (getRandomInt() % 32 - 16) / 82; + double offset_z = (getRandomInt() % 32 - 16) / 82; + EntityItem ei = new EntityItem( w, 0.5 + offset_x + x, 0.5 + offset_y + y, 0.2 + offset_z + z, i.copy() ); + w.spawnEntityInWorld( ei ); + } + } + } + } + } + + /* + * Utility function to get the full inventory for a Double Chest in the World. + */ + public static IInventory GetChestInv(Object te) + { + TileEntityChest teA = (TileEntityChest) te; + TileEntity teB = null; + int myBlockID = teA.worldObj.getBlockId( teA.xCoord, teA.yCoord, teA.zCoord ); + + if ( teA.worldObj.getBlockId( teA.xCoord + 1, teA.yCoord, teA.zCoord ) == myBlockID ) + { + teB = teA.worldObj.getBlockTileEntity( teA.xCoord + 1, teA.yCoord, teA.zCoord ); + if ( !(teB instanceof TileEntityChest) ) + teB = null; + } + + if ( teB == null ) + { + if ( teA.worldObj.getBlockId( teA.xCoord - 1, teA.yCoord, teA.zCoord ) == myBlockID ) + { + teB = teA.worldObj.getBlockTileEntity( teA.xCoord - 1, teA.yCoord, teA.zCoord ); + if ( !(teB instanceof TileEntityChest) ) + teB = null; + else + { + TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if ( teB == null ) + { + if ( teA.worldObj.getBlockId( teA.xCoord, teA.yCoord, teA.zCoord + 1 ) == myBlockID ) + { + teB = teA.worldObj.getBlockTileEntity( teA.xCoord, teA.yCoord, teA.zCoord + 1 ); + if ( !(teB instanceof TileEntityChest) ) + teB = null; + } + } + + if ( teB == null ) + { + if ( teA.worldObj.getBlockId( teA.xCoord, teA.yCoord, teA.zCoord - 1 ) == myBlockID ) + { + teB = teA.worldObj.getBlockTileEntity( teA.xCoord, teA.yCoord, teA.zCoord - 1 ); + if ( !(teB instanceof TileEntityChest) ) + teB = null; + else + { + TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if ( teB == null ) + return teA; + + return new InventoryLargeChest( "", teA, (TileEntityChest) teB ); + } + + public static boolean isModLoaded(String modid) + { + try + { + // if this fails for some reason, try the other method. + return Loader.isModLoaded( modid ); + } + catch (Throwable e) + { + } + + for (ModContainer f : Loader.instance().getActiveModList()) + { + if ( f.getModId().equals( modid ) ) + { + return true; + } + } + return false; + } + + public static ItemStack findMatchingRecipeOutput(InventoryCrafting ic, World worldObj) + { + return CraftingManager.getInstance().findMatchingRecipe( ic, worldObj ); + } + + @SideOnly(Side.CLIENT) + public static List getTooltip(Object o) + { + if ( o == null ) + return new ArrayList(); + + ItemStack itemStack = null; + if ( o instanceof AEItemStack ) + { + AEItemStack ais = (AEItemStack) o; + return ais.getToolTip(); + } + else if ( o instanceof ItemStack ) + itemStack = (ItemStack) o; + else + return new ArrayList(); + + try + { + return itemStack.getTooltip( Minecraft.getMinecraft().thePlayer, false ); + } + catch (Exception errB) + { + return new ArrayList(); + } + } + + public static String getItemDisplayName(Object o) + { + if ( o == null ) + return "** Null"; + + ItemStack itemStack = null; + if ( o instanceof AEItemStack ) + { + String n = ((AEItemStack) o).getDisplayName(); + return n == null ? "** Null" : n; + } + else if ( o instanceof ItemStack ) + itemStack = (ItemStack) o; + else + return "**Invalid Object"; + + try + { + String name = itemStack.getDisplayName(); + if ( name == null || name.equals( "" ) ) + name = itemStack.getItem().getUnlocalizedName( itemStack ); + return name == null ? "** Null" : name; + } + catch (Exception errA) + { + try + { + String n = itemStack.getUnlocalizedName(); + return n == null ? "** Null" : n; + } + catch (Exception errB) + { + return "** Exception"; + } + } + } + + public static boolean hasSpecialComparison(IAEItemStack willAdd) + { + if ( willAdd == null ) + return false; + IAETagCompound tag = willAdd.getTagCompound(); + if ( tag != null && ((AESharedNBT) tag).getSpecialComparison() != null ) + return true; + return false; + } + + public static boolean hasSpecialComparison(ItemStack willAdd) + { + if ( AESharedNBT.isShared( willAdd.getTagCompound() ) ) + { + if ( ((AESharedNBT) willAdd.getTagCompound()).getSpecialComparison() != null ) + return true; + } + return false; + } + + public static boolean isWrench(EntityPlayer player, ItemStack eq, int x, int y, int z) + { + if ( eq != null ) + { + try + { + if ( eq.getItem() instanceof IToolWrench ) + { + IToolWrench wrench = (IToolWrench) eq.getItem(); + return wrench.canWrench( player, x, y, z ); + } + } + catch (Throwable _) + { // explodes without BC + if ( eq.getItem() instanceof IAEWrench ) + { + IAEWrench wrench = (IAEWrench) eq.getItem(); + return wrench.canWrench( eq, player, x, y, z ); + } + } + } + return false; + } + + public static boolean isChargeable(ItemStack i) + { + if ( i == null ) + return false; + Item it = i.getItem(); + if ( it instanceof IAEItemPowerStorage ) + { + return ((IAEItemPowerStorage) it).getPowerFlow( i ) != AccessRestriction.READ; + } + return false; + } + + private static WeakHashMap fakePlayers = new WeakHashMap(); + + public static EntityPlayer getPlayer(World w) + { + EntityPlayer wrp = fakePlayers.get( w ); + if ( wrp != null ) + return wrp; + + EntityPlayer p = new FakePlayer( w, "[AppEng]" ); + fakePlayers.put( w, p ); + return p; + } + + public static int MC2MEColor(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; + } + + public static int findEmpty(Object[] l) + { + for (int x = 0; x < l.length; x++) + { + if ( l[x] == null ) + return x; + } + return -1; + } + + public static T pickRandom(Collection outs) + { + int index = rdnSrc.nextInt( outs.size() ); + Iterator i = outs.iterator(); + while (i.hasNext() && index > 0) + i.next(); + if ( i.hasNext() ) + return i.next(); + return null; // wtf? + } + + public static boolean blockAtLocationIs(IBlockAccess w, int x, int y, int z, AEItemDefinition def) + { + int blk = w.getBlockId( x, y, z ); + return def.block() == Block.blocksList[blk]; + } + + public static ForgeDirection rotateAround(ForgeDirection forward, ForgeDirection axis) + { + if ( axis == ForgeDirection.UNKNOWN || forward == ForgeDirection.UNKNOWN ) + return forward; + + switch (forward) + { + case DOWN: + switch (axis) + { + case DOWN: + return forward; + case UP: + return forward; + case NORTH: + return ForgeDirection.EAST; + case SOUTH: + return ForgeDirection.WEST; + case EAST: + return ForgeDirection.NORTH; + case WEST: + return ForgeDirection.SOUTH; + default: + break; + } + break; + case UP: + switch (axis) + { + case NORTH: + return ForgeDirection.WEST; + case SOUTH: + return ForgeDirection.EAST; + case EAST: + return ForgeDirection.SOUTH; + case WEST: + return ForgeDirection.NORTH; + default: + break; + } + break; + case NORTH: + switch (axis) + { + case UP: + return ForgeDirection.WEST; + case DOWN: + return ForgeDirection.EAST; + case EAST: + return ForgeDirection.UP; + case WEST: + return ForgeDirection.DOWN; + default: + break; + } + break; + case SOUTH: + switch (axis) + { + case UP: + return ForgeDirection.EAST; + case DOWN: + return ForgeDirection.WEST; + case EAST: + return ForgeDirection.DOWN; + case WEST: + return ForgeDirection.UP; + default: + break; + } + break; + case EAST: + switch (axis) + { + case UP: + return ForgeDirection.NORTH; + case DOWN: + return ForgeDirection.SOUTH; + case NORTH: + return ForgeDirection.UP; + case SOUTH: + return ForgeDirection.DOWN; + default: + break; + } + case WEST: + switch (axis) + { + case UP: + return ForgeDirection.SOUTH; + case DOWN: + return ForgeDirection.NORTH; + case NORTH: + return ForgeDirection.DOWN; + case SOUTH: + return ForgeDirection.UP; + default: + break; + } + default: + break; + } + return forward; + } + + @SideOnly(Side.CLIENT) + public static String gui_localize(String string) + { + AELog.localization( "gui", string ); + return StatCollector.translateToLocal( string ); + } + + public static boolean isSameItemType(ItemStack ol, ItemStack op) + { + if ( ol != null && op != null && ol.itemID == op.itemID ) + { + if ( ol.isItemStackDamageable() ) + return true; + return ol.getItemDamage() == ol.getItemDamage(); + } + return false; + } + + public static boolean isSameItem(ItemStack ol, ItemStack op) + { + return ol != null && op != null && ol.isItemEqual( op ); + } + + public static ItemStack cloneItemStack(ItemStack a) + { + return a.copy(); + } + + public static boolean isSameItemPrecise(ItemStack is, ItemStack filter) + { + return isSameItem( is, filter ); + } + + public static boolean isSameItemFuzzy(ItemStack a, ItemStack b, FuzzyMode Mode) + { + if ( a == null && b == null ) + { + return true; + } + + if ( a == null ) + { + return false; + } + + if ( b == null ) + { + return false; + } + + /* + * if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID == + * b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); } + */ + + // test damageable items.. + if ( a.itemID != 0 && b.itemID != 0 && a.getItem().isDamageable() && a.itemID == b.itemID ) + { + try + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); + } + else + { + float APercentDamaged = 1.0f - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); + float BPercentDamaged = 1.0f - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + catch (Throwable e) + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); + } + else + { + float APercentDamaged = (float) a.getItemDamage() / (float) a.getMaxDamage(); + float BPercentDamaged = (float) b.getItemDamage() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + } + + /* + * // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b ); + * + * if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a = + * Platform.getSharedItemStack( AEItemStack.create( a ) ); } + * + * if ( b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = Platform.getSharedItemStack( + * AEItemStack.create( b ) ); } + * + * // test regular items with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared( + * b.getTagCompound() ) && a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound) + * a.getTagCompound()).compareFuzzyWithRegistry( (AppEngSharedNBTTagCompound) b.getTagCompound() ); } } + */ + + return a.isItemEqual( b ); + } + + public static LookDirection getPlayerRay(EntityPlayer player) + { + float f = 1.0F; + float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f; + float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f; + double d0 = player.prevPosX + (player.posX - player.prevPosX) * (double) f; + double d1 = player.prevPosY + (player.posY - player.prevPosY) * (double) f + + (double) (player.worldObj.isRemote ? player.getEyeHeight() - player.getDefaultEyeHeight() : player.getEyeHeight()); // isRemote + + double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * (double) f; + Vec3 vec3 = player.worldObj.getWorldVec3Pool().getVecFromPool( d0, d1, d2 ); + float f3 = MathHelper.cos( -f2 * 0.017453292F - (float) Math.PI ); + float f4 = MathHelper.sin( -f2 * 0.017453292F - (float) Math.PI ); + float f5 = -MathHelper.cos( -f1 * 0.017453292F ); + float f6 = MathHelper.sin( -f1 * 0.017453292F ); + float f7 = f4 * f5; + float f8 = f3 * f5; + double d3 = 5.0D; + + if ( player instanceof EntityPlayerMP ) + { + d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance(); + } + Vec3 vec31 = vec3.addVector( (double) f7 * d3, (double) f6 * d3, (double) f8 * d3 ); + return new LookDirection( vec3, vec31 ); + } + + public static long nanoTime() + { + if ( Configuration.instance.enableNetworkProfiler ) + return System.nanoTime(); + return 0; + } + + public static IAEItemStack poweredExtraction(IEnergySource energy, IMEInventory cell, IAEItemStack input) + { + IAEItemStack possible = cell.extractItems( input.copy(), Actionable.SIMULATE ); + + long retrieved = 0; + if ( possible != null ) + retrieved = possible.getStackSize(); + + double availablePower = energy.extractAEPower( retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG ); + + long itemToExtract = Math.min( (long) (availablePower + 0.9), retrieved ); + + if ( itemToExtract > 0 ) + { + energy.extractAEPower( retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG ); + + possible.setStackSize( itemToExtract ); + return cell.extractItems( possible, Actionable.MODULATE ); + } + + return null; + } + + public static IAEItemStack poweredInsert(IEnergySource energy, IMEInventory cell, IAEItemStack input) + { + IAEItemStack possible = cell.injectItems( input.copy(), Actionable.SIMULATE ); + + long stored = input.getStackSize(); + if ( possible != null ) + stored -= possible.getStackSize(); + + double availablePower = energy.extractAEPower( stored, Actionable.SIMULATE, PowerMultiplier.CONFIG ); + + long itemToAdd = Math.min( (long) (availablePower + 0.9), stored ); + + if ( itemToAdd > 0 ) + { + energy.extractAEPower( stored, Actionable.MODULATE, PowerMultiplier.CONFIG ); + + if ( itemToAdd < input.getStackSize() ) + { + IAEItemStack split = input.copy(); + split.decStackSize( itemToAdd ); + input.setStackSize( itemToAdd ); + split.add( cell.injectItems( input, Actionable.MODULATE ) ); + return split; + } + return cell.injectItems( input, Actionable.MODULATE ); + } + + return input; + } + + public static void postChanges(IStorageGrid gs, ItemStack removed, ItemStack added) + { + if ( removed != null ) + { + IMEInventory myItems = AEApi.instance().registries().cell().getCellInventory( removed, StorageChannel.ITEMS ); + + if ( myItems != null ) + { + for (IAEItemStack is : myItems.getAvailableItems( new ItemList() )) + { + is.setStackSize( -is.getStackSize() ); + gs.postAlterationOfStoredItems( StorageChannel.ITEMS, is ); + } + } + + IMEInventory myFluids = AEApi.instance().registries().cell().getCellInventory( removed, StorageChannel.FLUIDS ); + + if ( myFluids != null ) + { + for (IAEFluidStack is : myFluids.getAvailableItems( new ItemList() )) + { + is.setStackSize( -is.getStackSize() ); + gs.postAlterationOfStoredItems( StorageChannel.ITEMS, is ); + } + } + } + + if ( added != null ) + { + IMEInventory myItems = AEApi.instance().registries().cell().getCellInventory( added, StorageChannel.ITEMS ); + + if ( myItems != null ) + { + for (IAEItemStack is : myItems.getAvailableItems( new ItemList() )) + { + gs.postAlterationOfStoredItems( StorageChannel.ITEMS, is ); + } + } + + IMEInventory myFluids = AEApi.instance().registries().cell().getCellInventory( added, StorageChannel.FLUIDS ); + + if ( myFluids != null ) + { + for (IAEFluidStack is : myFluids.getAvailableItems( new ItemList() )) + { + gs.postAlterationOfStoredItems( StorageChannel.ITEMS, is ); + } + } + } + } + + static public > void postListChanges(IItemList before, IItemList after, IMEMontorHandlerReciever meMonitorPassthu) + { + for (T is : before) + is.setStackSize( -is.getStackSize() ); + + for (T is : after) + before.add( is ); + + for (T is : before) + { + if ( is.getStackSize() != 0 ) + { + meMonitorPassthu.postChange( is ); + } + } + } + +} diff --git a/util/ReadOnlyCollection.java b/util/ReadOnlyCollection.java new file mode 100644 index 00000000..739dc541 --- /dev/null +++ b/util/ReadOnlyCollection.java @@ -0,0 +1,41 @@ +package appeng.util; + +import java.util.Collection; +import java.util.Iterator; + +import appeng.api.util.IReadOnlyCollection; + +public class ReadOnlyCollection implements IReadOnlyCollection +{ + + private final Collection c; + + public ReadOnlyCollection(Collection in) { + c = in; + } + + @Override + public Iterator iterator() + { + return c.iterator(); + } + + @Override + public int size() + { + return c.size(); + } + + @Override + public boolean isEmpty() + { + return c.isEmpty(); + } + + @Override + public boolean contains(Object node) + { + return c.contains( node ); + } + +} diff --git a/util/SettingsFrom.java b/util/SettingsFrom.java new file mode 100644 index 00000000..0bd4e79f --- /dev/null +++ b/util/SettingsFrom.java @@ -0,0 +1,10 @@ +package appeng.util; + +public enum SettingsFrom +{ + // moved the item, and replaced it. + DISMANTLE_ITEM, + + // used memory card? + MEMORY_CARD +} diff --git a/util/SortedList.java b/util/SortedList.java new file mode 100644 index 00000000..531e2736 --- /dev/null +++ b/util/SortedList.java @@ -0,0 +1,195 @@ +package appeng.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +public class SortedList implements Iterable, List, Cloneable { + + private boolean sorted = true; + private final Comparator comp; + private final LinkedList storage = new LinkedList(); + + private void makeSorted() { + if (!sorted) { + sorted = true; + Collections.sort(storage, comp); + } + } + + public SortedList(Comparator comp) { + this.comp = comp; + } + + @Override + public boolean add(T input) { + sorted = false; + return storage.add(input); + } + + @Override + public boolean addAll(Collection input) { + if (!input.isEmpty()) + sorted = false; + return storage.addAll(input); + } + + @Override + public void clear() { + sorted = true; + storage.clear(); + } + + @Override + public boolean contains(Object input) { + return storage.contains(input); + } + + @Override + public boolean containsAll(Collection input) { + return storage.containsAll(input); + } + + @Override + public boolean isEmpty() { + return isEmpty(); + } + + @Override + public Iterator iterator() { + makeSorted(); + return storage.iterator(); + } + + public Iterator reverseIterator() { + makeSorted(); + final ListIterator listIterator = listIterator(size()); + + return new Iterator() { + + public boolean hasNext() { + return listIterator.hasPrevious(); + } + + public T next() { + return listIterator.previous(); + } + + public void remove() { + listIterator.remove(); + } + + }; + } + + @Override + public boolean remove(Object input) { + return storage.remove(input); + } + + @Override + public boolean removeAll(Collection input) { + return storage.removeAll(input); + } + + @Override + public boolean retainAll(Collection input) { + return storage.retainAll(input); + } + + @Override + public int size() { + return storage.size(); + } + + @Override + public Object[] toArray() { + return storage.toArray(); + } + + @Override + public X[] toArray(X[] input) { + return storage.toArray(input); + } + + public Comparator comparator() { + return comp; + } + + public T first() { + makeSorted(); + return storage.peekFirst(); + } + + public T last() { + makeSorted(); + return storage.peekLast(); + } + + @Override + public void add(int index, T element) { + makeSorted(); + sorted = false; + add(index, element); + } + + @Override + public boolean addAll(int index, Collection c) { + sorted = false; + return addAll(index, c); + } + + @Override + public T get(int index) { + makeSorted(); + return get(index); + } + + @Override + public int indexOf(Object o) { + makeSorted(); + return indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + makeSorted(); + return lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + makeSorted(); + return listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + makeSorted(); + return listIterator(index); + } + + @Override + public T remove(int index) { + makeSorted(); + return remove(index); + } + + @Override + public T set(int index, T element) { + makeSorted(); + sorted = false; + return set(index, element); + } + + @Override + public List subList(int fromIndex, int toIndex) { + makeSorted(); + return storage.subList(fromIndex, toIndex); + } + +} diff --git a/util/inv/AdaptorBCPipe.java b/util/inv/AdaptorBCPipe.java new file mode 100644 index 00000000..a0f4604d --- /dev/null +++ b/util/inv/AdaptorBCPipe.java @@ -0,0 +1,89 @@ +package appeng.util.inv; + +import java.util.Iterator; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.FuzzyMode; +import appeng.integration.modules.BC; +import appeng.util.InventoryAdaptor; +import appeng.util.iterators.NullIterator; + +public class AdaptorBCPipe extends InventoryAdaptor +{ + + private TileEntity i; + private ForgeDirection d; + + public AdaptorBCPipe(TileEntity s, ForgeDirection dd) { + if ( BC.instance != null ) + { + if ( BC.instance.isPipe( s, dd ) ) + { + i = s; + d = dd; + } + } + } + + @Override + public ItemStack removeSimilarItems(int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + return null; + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + return null; + } + + @Override + public ItemStack removeItems(int how_many, ItemStack filter, IInventoryDestination destination) + { + return null; + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack filter, IInventoryDestination destination) + { + return null; + } + + @Override + public ItemStack addItems(ItemStack A) + { + if ( i == null ) + return A; + if ( A == null ) + return null; + if ( A.stackSize == 0 ) + return null; + + if ( BC.instance.addItemsToPipe( i, A, d ) ) + return null; + return A; + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + if ( i == null ) + return A; + return null; + } + + @Override + public boolean containsItems() + { + return false; + } + + @Override + public Iterator iterator() + { + return new NullIterator(); + } + +} diff --git a/util/inv/AdaptorIInventory.java b/util/inv/AdaptorIInventory.java new file mode 100644 index 00000000..4c406ef3 --- /dev/null +++ b/util/inv/AdaptorIInventory.java @@ -0,0 +1,353 @@ +package appeng.util.inv; + +import java.util.Iterator; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; + +public class AdaptorIInventory extends InventoryAdaptor +{ + + private IInventory i; + private boolean wrapperEnabled; + + public AdaptorIInventory(IInventory s) { + i = s; + wrapperEnabled = s instanceof IInventoryWrapper; + } + + boolean canRemoveStackFromSlot(int x, ItemStack is) + { + if ( wrapperEnabled ) + return ((IInventoryWrapper) i).canRemoveItemFromSlot( x, is ); + return true; + } + + @Override + public boolean containsItems() + { + int s = i.getSizeInventory(); + for (int x = 0; x < s; x++) + { + if ( i.getStackInSlot( x ) != null ) + return true; + } + return false; + } + + @Override + public ItemStack removeSimilarItems(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + int s = i.getSizeInventory(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.getStackInSlot( x ); + if ( is != null && canRemoveStackFromSlot( x, is ) && (filter == null || Platform.isSameItemFuzzy( is, filter, fuzzyMode )) ) + { + int lhow_many = how_many; + if ( lhow_many > is.stackSize ) + lhow_many = is.stackSize; + if ( destination != null && !destination.canInsert( is ) ) + lhow_many = 0; + + ItemStack rv = null; + if ( lhow_many > 0 ) + { + rv = is.copy(); + rv.stackSize = lhow_many; + + if ( is.stackSize == rv.stackSize ) + i.setInventorySlotContents( x, null ); + else + { + ItemStack po = is.copy(); + po.stackSize -= rv.stackSize; + i.setInventorySlotContents( x, po ); + } + } + + if ( rv != null ) + { + i.onInventoryChanged(); + return rv; + } + } + } + return null; + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + int s = i.getSizeInventory(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.getStackInSlot( x ); + + if ( is != null && canRemoveStackFromSlot( x, is ) && (filter == null || Platform.isSameItemFuzzy( is, filter, fuzzyMode )) ) + { + int lhow_many = how_many; + if ( lhow_many > is.stackSize ) + lhow_many = is.stackSize; + if ( destination != null && !destination.canInsert( is ) ) + lhow_many = 0; + + if ( lhow_many > 0 ) + { + ItemStack rv = is.copy(); + rv.stackSize = lhow_many; + return rv; + } + } + } + return null; + } + + @Override + public ItemStack removeItems(int how_many, ItemStack filter, IInventoryDestination destination) + { + int s = i.getSizeInventory(); + ItemStack rv = null; + + for (int x = 0; x < s && how_many > 0; x++) + { + ItemStack is = i.getStackInSlot( x ); + if ( is != null && canRemoveStackFromSlot( x, is ) && (filter == null || Platform.isSameItemPrecise( is, filter )) ) + { + int lhow_many = how_many; + if ( lhow_many > is.stackSize ) + lhow_many = is.stackSize; + if ( destination != null && !destination.canInsert( is ) ) + lhow_many = 0; + + if ( lhow_many > 0 ) + { + if ( rv == null ) + { + rv = is.copy(); + rv.stackSize = lhow_many; + how_many -= lhow_many; + } + else + { + rv.stackSize += lhow_many; + how_many -= lhow_many; + } + + if ( is.stackSize == lhow_many ) + i.setInventorySlotContents( x, null ); + else + { + ItemStack po = is.copy(); + po.stackSize -= lhow_many; + i.setInventorySlotContents( x, po ); + } + } + } + } + + if ( rv != null ) + i.onInventoryChanged(); + + return rv; + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack filter, IInventoryDestination destination) + { + int s = i.getSizeInventory(); + ItemStack rv = null; + + for (int x = 0; x < s && how_many > 0; x++) + { + ItemStack is = i.getStackInSlot( x ); + if ( is != null && canRemoveStackFromSlot( x, is ) && (filter == null || Platform.isSameItemPrecise( is, filter )) ) + { + int lhow_many = how_many; + if ( lhow_many > is.stackSize ) + lhow_many = is.stackSize; + if ( destination != null && !destination.canInsert( is ) ) + lhow_many = 0; + + if ( lhow_many > 0 ) + { + if ( rv == null ) + { + rv = is.copy(); + rv.stackSize = lhow_many; + how_many -= lhow_many; + } + else + { + rv.stackSize += lhow_many; + how_many -= lhow_many; + } + } + } + } + + return rv; + } + + @Override + public ItemStack addItems(ItemStack A) + { + if ( A == null ) + return null; + if ( A.stackSize == 0 ) + return null; + + ItemStack left = A.copy(); + + int stack_limit = A.getMaxStackSize(); + if ( stack_limit > i.getInventoryStackLimit() ) + stack_limit = i.getInventoryStackLimit(); + + int s = i.getSizeInventory(); + for (int pass = 0; pass < 2; pass++) + { + for (int x = 0; x < s; x++) + { + if ( i.isItemValidForSlot( x, A ) ) + { + ItemStack is = i.getStackInSlot( x ); + if ( is == null && pass != 0 ) + { + ItemStack thisSlot = left.copy(); + if ( thisSlot.stackSize > stack_limit ) + thisSlot.stackSize = stack_limit; + left.stackSize -= thisSlot.stackSize; + + i.setInventorySlotContents( x, thisSlot ); + + if ( left.stackSize <= 0 ) + { + i.onInventoryChanged(); + return null; + } + } + else if ( is != null ) + { + if ( Platform.isSameItem( is, left ) ) + { + if ( is.stackSize < stack_limit ) + { + int room = stack_limit - is.stackSize; + int used = left.stackSize; + if ( used > room ) + used = room; + + is.stackSize += used; + i.setInventorySlotContents( x, is ); + + left.stackSize -= used; + if ( left.stackSize <= 0 ) + { + i.onInventoryChanged(); + return null; + } + } + } + } + } + } + } + + if ( left.stackSize != A.stackSize ) + i.onInventoryChanged(); + + return left; + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + if ( A == null ) + return A; + ItemStack left = A.copy(); + + int stack_limit = A.getMaxStackSize(); + if ( stack_limit > i.getInventoryStackLimit() ) + stack_limit = i.getInventoryStackLimit(); + + int s = i.getSizeInventory(); + for (int x = 0; x < s; x++) + { + if ( i.isItemValidForSlot( x, A ) ) + { + ItemStack is = i.getStackInSlot( x ); + if ( is == null ) + { + ItemStack thisSlot = left.copy(); + if ( thisSlot.stackSize > stack_limit ) + thisSlot.stackSize = stack_limit; + left.stackSize -= thisSlot.stackSize; + + if ( left.stackSize <= 0 ) + { + return null; + } + } + else + { + if ( Platform.isSameItem( is, left ) ) + { + if ( is.stackSize < stack_limit ) + { + int room = stack_limit - is.stackSize; + int used = left.stackSize; + if ( used > room ) + used = room; + + left.stackSize -= used; + if ( left.stackSize <= 0 ) + { + return null; + } + } + } + } + } + } + + return left; + } + + class InvIterator implements Iterator + { + + final ItemSlot is = new ItemSlot(); + int x = 0; + + @Override + public boolean hasNext() + { + return x < i.getSizeInventory(); + } + + @Override + public ItemSlot next() + { + is.slot = x; + is.itemStack = i.getStackInSlot( x++ ); + return is; + } + + @Override + public void remove() + { + // nothing! + } + + }; + + @Override + public Iterator iterator() + { + return new InvIterator(); + } + +} diff --git a/util/inv/AdaptorISpecialInventory.java b/util/inv/AdaptorISpecialInventory.java new file mode 100644 index 00000000..d89a3c00 --- /dev/null +++ b/util/inv/AdaptorISpecialInventory.java @@ -0,0 +1,112 @@ +package appeng.util.inv; + +import java.util.Iterator; + +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import buildcraft.api.inventory.ISpecialInventory; + +public class AdaptorISpecialInventory extends InventoryAdaptor +{ + + private AdaptorIInventory remover; + + private ISpecialInventory i; + private ForgeDirection d; + + public AdaptorISpecialInventory(ISpecialInventory s, ForgeDirection dd) { + i = s; + d = dd; + + if ( s instanceof ISidedInventory ) + remover = new AdaptorIInventory( new WrapperMCISidedInventory( (ISidedInventory) s, d ) ); + else + remover = new AdaptorIInventory( s ); + } + + @Override + public ItemStack removeSimilarItems(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + return remover.removeSimilarItems( how_many, filter, fuzzyMode, destination ); + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination) + { + return remover.simulateSimilarRemove( how_many, filter, fuzzyMode, destination ); + } + + @Override + public ItemStack removeItems(int how_many, ItemStack filter, IInventoryDestination destination) + { + return remover.removeItems( how_many, filter, destination ); + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack filter, IInventoryDestination destination) + { + return remover.simulateRemove( how_many, filter, destination ); + } + + @Override + public ItemStack addItems(ItemStack A) + { + if ( A == null ) + return null; + if ( A.stackSize == 0 ) + return null; + + int used = i.addItem( A, true, d ); + ItemStack out = A.copy(); + out.stackSize -= used; + if ( out.stackSize > 0 ) + return out; + return null; + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + int used = i.addItem( A, false, d ); + ItemStack out = A.copy(); + out.stackSize -= used; + if ( out.stackSize > 0 ) + return out; + return null; + } + + @Override + public boolean containsItems() + { + if ( i instanceof ISidedInventory ) + { + ISidedInventory sided = (ISidedInventory) i; + int slots[] = sided.getAccessibleSlotsFromSide( d.ordinal() ); + if ( slots == null ) + return false; + + int s = slots.length; + for (int x = 0; x < s; x++) + if ( i.getStackInSlot( slots[x] ) != null ) + return true; + + return false; + } + + int s = i.getSizeInventory(); + for (int x = 0; x < s; x++) + if ( i.getStackInSlot( x ) != null ) + return true; + return false; + } + + @Override + public Iterator iterator() + { + return remover.iterator(); + } + +} diff --git a/util/inv/AdaptorList.java b/util/inv/AdaptorList.java new file mode 100644 index 00000000..0f6f1664 --- /dev/null +++ b/util/inv/AdaptorList.java @@ -0,0 +1,186 @@ +package appeng.util.inv; + +import java.util.Iterator; +import java.util.List; + +import net.minecraft.item.ItemStack; +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.iterators.StackToSlotIterator; + +public class AdaptorList extends InventoryAdaptor +{ + + private List i; + + public AdaptorList(List s) { + i = s; + } + + @Override + public ItemStack removeSimilarItems(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( is != null && (filter == null || Platform.isSameItemFuzzy( is, filter, fuzzyMode )) ) + { + if ( how_many > is.stackSize ) + how_many = is.stackSize; + if ( dest != null && !dest.canInsert( is ) ) + how_many = 0; + + if ( how_many > 0 ) + { + ItemStack rv = is.copy(); + rv.stackSize = how_many; + is.stackSize -= how_many; + + // remove it.. + if ( is.stackSize <= 0 ) + i.remove( x ); + + return rv; + } + } + } + return null; + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( is != null && (filter == null || Platform.isSameItemFuzzy( is, filter, fuzzyMode )) ) + { + if ( how_many > is.stackSize ) + how_many = is.stackSize; + if ( dest != null && !dest.canInsert( is ) ) + how_many = 0; + + if ( how_many > 0 ) + { + ItemStack rv = is.copy(); + rv.stackSize = how_many; + return rv; + } + } + } + return null; + + } + + @Override + public ItemStack removeItems(int how_many, ItemStack filter, IInventoryDestination dest) + { + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( is != null && (filter == null || Platform.isSameItemPrecise( is, filter )) ) + { + if ( how_many > is.stackSize ) + how_many = is.stackSize; + if ( dest != null && !dest.canInsert( is ) ) + how_many = 0; + + if ( how_many > 0 ) + { + ItemStack rv = is.copy(); + rv.stackSize = how_many; + is.stackSize -= how_many; + + // remove it.. + if ( is.stackSize <= 0 ) + i.remove( x ); + + return rv; + } + } + } + return null; + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack filter, IInventoryDestination dest) + { + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( is != null && (filter == null || Platform.isSameItemPrecise( is, filter )) ) + { + if ( how_many > is.stackSize ) + how_many = is.stackSize; + if ( dest != null && !dest.canInsert( is ) ) + how_many = 0; + + if ( how_many > 0 ) + { + ItemStack rv = is.copy(); + rv.stackSize = how_many; + return rv; + } + } + } + return null; + + } + + @Override + public ItemStack addItems(ItemStack A) + { + if ( A == null ) + return null; + if ( A.stackSize == 0 ) + return null; + + ItemStack left = A.copy(); + + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( Platform.isSameItem( is, left ) ) + { + is.stackSize += left.stackSize; + return null; + } + } + + i.add( left ); + return null; + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + return null; + } + + @Override + public boolean containsItems() + { + + int s = i.size(); + for (int x = 0; x < s; x++) + { + ItemStack is = i.get( x ); + if ( is != null ) + return true; + } + return false; + } + + @Override + public Iterator iterator() + { + return new StackToSlotIterator( i.iterator() ); + } + +} diff --git a/util/inv/AdaptorPlayerHand.java b/util/inv/AdaptorPlayerHand.java new file mode 100644 index 00000000..547a7e27 --- /dev/null +++ b/util/inv/AdaptorPlayerHand.java @@ -0,0 +1,185 @@ +package appeng.util.inv; + +import java.util.Iterator; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import appeng.util.iterators.NullIterator; + +/* + * Lets you do simply tests with the players cursor, without messing with the specifics. + */ +public class AdaptorPlayerHand extends InventoryAdaptor +{ + + private EntityPlayer p; + + public AdaptorPlayerHand(EntityPlayer _p) { + p = _p; + } + + @Override + public ItemStack removeSimilarItems(int how_many, ItemStack Filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + ItemStack hand = p.inventory.getItemStack(); + if ( hand == null ) + return null; + + if ( Filter == null || Platform.isSameItemFuzzy( Filter, hand, fuzzyMode ) ) + { + ItemStack result = hand.copy(); + result.stackSize = hand.stackSize > how_many ? how_many : hand.stackSize; + hand.stackSize -= how_many; + if ( hand.stackSize <= 0 ) + p.inventory.setItemStack( null ); + return result; + } + + return null; + } + + @Override + public ItemStack simulateSimilarRemove(int how_many, ItemStack Filter, FuzzyMode fuzzyMode, IInventoryDestination dest) + { + + ItemStack hand = p.inventory.getItemStack(); + if ( hand == null ) + return null; + + if ( Filter == null || Platform.isSameItemFuzzy( Filter, hand, fuzzyMode ) ) + { + ItemStack result = hand.copy(); + result.stackSize = hand.stackSize > how_many ? how_many : hand.stackSize; + return result; + } + + return null; + } + + @Override + public ItemStack removeItems(int how_many, ItemStack Filter, IInventoryDestination dest) + { + ItemStack hand = p.inventory.getItemStack(); + if ( hand == null ) + return null; + + if ( Filter == null || Platform.isSameItemPrecise( Filter, hand ) ) + { + ItemStack result = hand.copy(); + result.stackSize = hand.stackSize > how_many ? how_many : hand.stackSize; + hand.stackSize -= how_many; + if ( hand.stackSize <= 0 ) + p.inventory.setItemStack( null ); + return result; + } + + return null; + } + + @Override + public ItemStack simulateRemove(int how_many, ItemStack Filter, IInventoryDestination dest) + { + + ItemStack hand = p.inventory.getItemStack(); + if ( hand == null ) + return null; + + if ( Filter == null || Platform.isSameItemPrecise( Filter, hand ) ) + { + ItemStack result = hand.copy(); + result.stackSize = hand.stackSize > how_many ? how_many : hand.stackSize; + return result; + } + + return null; + } + + @Override + public ItemStack addItems(ItemStack A) + { + + if ( A == null ) + return null; + if ( A.stackSize == 0 ) + return null; + if ( p == null ) + return A; + if ( p.inventory == null ) + return A; + + ItemStack hand = p.inventory.getItemStack(); + + if ( hand != null && !Platform.isSameItem( A, hand ) ) + return A; + + int original = 0; + ItemStack newHand = null; + if ( hand == null ) + newHand = A.copy(); + else + { + newHand = hand; + original = hand.stackSize; + newHand.stackSize += A.stackSize; + } + + if ( newHand.stackSize > newHand.getMaxStackSize() ) + { + newHand.stackSize = newHand.getMaxStackSize(); + ItemStack B = A.copy(); + B.stackSize -= newHand.stackSize - original; + p.inventory.setItemStack( newHand ); + return B; + } + + p.inventory.setItemStack( newHand ); + return null; + } + + @Override + public ItemStack simulateAdd(ItemStack A) + { + ItemStack hand = p.inventory.getItemStack(); + if ( A == null ) + return null; + + if ( hand != null && !Platform.isSameItem( A, hand ) ) + return A; + + int original = 0; + ItemStack newHand = null; + if ( hand == null ) + newHand = A.copy(); + else + { + newHand = hand.copy(); + original = hand.stackSize; + newHand.stackSize += A.stackSize; + } + + if ( newHand.stackSize > newHand.getMaxStackSize() ) + { + newHand.stackSize = newHand.getMaxStackSize(); + ItemStack B = A.copy(); + B.stackSize -= newHand.stackSize - original; + return B; + } + + return null; + } + + @Override + public boolean containsItems() + { + return p.inventory.getItemStack() != null; + } + + @Override + public Iterator iterator() + { + return new NullIterator(); + } +} diff --git a/util/inv/AdaptorPlayerInventory.java b/util/inv/AdaptorPlayerInventory.java new file mode 100644 index 00000000..c68c9f11 --- /dev/null +++ b/util/inv/AdaptorPlayerInventory.java @@ -0,0 +1,99 @@ +package appeng.util.inv; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class AdaptorPlayerInventory implements IInventory +{ + + private InventoryPlayer src; + private int min; + private int size; + + public AdaptorPlayerInventory(InventoryPlayer a) { + src = a; + min = 0; // a.getStartInventorySide( d ); + size = 36; // a.getSizeInventorySide( d ); + } + + @Override + public int getSizeInventory() + { + return size; + } + + @Override + public ItemStack getStackInSlot(int var1) + { + return src.getStackInSlot( var1 + min ); + } + + @Override + public ItemStack decrStackSize(int var1, int var2) + { + return src.decrStackSize( min + var1, var2 ); + } + + @Override + public ItemStack getStackInSlotOnClosing(int var1) + { + return src.getStackInSlotOnClosing( min + var1 ); + } + + @Override + public void setInventorySlotContents(int var1, ItemStack var2) + { + src.setInventorySlotContents( var1 + min, var2 ); + } + + @Override + public String getInvName() + { + return src.getInvName(); + } + + @Override + public int getInventoryStackLimit() + { + return src.getInventoryStackLimit(); + } + + @Override + public void onInventoryChanged() + { + src.onInventoryChanged(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return src.isUseableByPlayer( var1 ); + } + + @Override + public void openChest() + { + src.openChest(); + } + + @Override + public void closeChest() + { + src.closeChest(); + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + +} diff --git a/util/inv/IInventoryDestination.java b/util/inv/IInventoryDestination.java new file mode 100644 index 00000000..1b7b8ccf --- /dev/null +++ b/util/inv/IInventoryDestination.java @@ -0,0 +1,10 @@ +package appeng.util.inv; + +import net.minecraft.item.ItemStack; + +public interface IInventoryDestination +{ + + public boolean canInsert(ItemStack stack); + +} diff --git a/util/inv/IInventoryWrapper.java b/util/inv/IInventoryWrapper.java new file mode 100644 index 00000000..5a8212fa --- /dev/null +++ b/util/inv/IInventoryWrapper.java @@ -0,0 +1,10 @@ +package appeng.util.inv; + +import net.minecraft.item.ItemStack; + +public interface IInventoryWrapper +{ + + boolean canRemoveItemFromSlot(int x, ItemStack is); + +} diff --git a/util/inv/IMEInventoryDestination.java b/util/inv/IMEInventoryDestination.java new file mode 100644 index 00000000..1753e158 --- /dev/null +++ b/util/inv/IMEInventoryDestination.java @@ -0,0 +1,32 @@ +package appeng.util.inv; + +import net.minecraft.item.ItemStack; +import appeng.api.config.Actionable; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEItemStack; +import appeng.util.item.AEItemStack; + +public class IMEInventoryDestination implements IInventoryDestination +{ + + IMEInventory me; + + public IMEInventoryDestination(IMEInventory o) { + me = o; + } + + @Override + public boolean canInsert(ItemStack stack) + { + + if ( stack == null ) + return false; + + IAEItemStack failed = me.injectItems( AEItemStack.create( stack ), Actionable.SIMULATE ); + + if ( failed == null ) + return true; + return failed.getStackSize() != stack.stackSize; + } + +} diff --git a/util/inv/ItemSlot.java b/util/inv/ItemSlot.java new file mode 100644 index 00000000..fca95850 --- /dev/null +++ b/util/inv/ItemSlot.java @@ -0,0 +1,11 @@ +package appeng.util.inv; + +import net.minecraft.item.ItemStack; + +public class ItemSlot +{ + + public int slot; + public ItemStack itemStack; + +} diff --git a/util/inv/WrapperChainedInventory.java b/util/inv/WrapperChainedInventory.java new file mode 100644 index 00000000..3613eb7a --- /dev/null +++ b/util/inv/WrapperChainedInventory.java @@ -0,0 +1,198 @@ +package appeng.util.inv; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class WrapperChainedInventory implements IInventory +{ + + class InvOffset + { + + int offset; + int size; + IInventory i; + }; + + int fullSize = 0; + + private List l; + private HashMap offsets; + + public WrapperChainedInventory(IInventory ilist) { + setInventory( ilist ); + } + + public WrapperChainedInventory(List ilist) { + setInventory( ilist ); + } + + public void calculateSizes() + { + offsets = new HashMap(); + + int offset = 0; + for (IInventory in : l) + { + InvOffset io = new InvOffset(); + io.offset = offset; + io.size = in.getSizeInventory(); + io.i = in; + + for (int y = 0; y < io.size; y++) + { + offsets.put( y + io.offset, io ); + } + + offset += io.size; + } + + fullSize = offset; + } + + public void setInventory(IInventory a) + { + l = new ArrayList(); + l.add( a ); + calculateSizes(); + } + + public void setInventory(List a) + { + l = a; + calculateSizes(); + } + + public IInventory getInv(int idx) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return io.i; + } + return null; + } + + public int getInvSlot(int idx) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return idx - io.offset; + } + return 0; + } + + @Override + public int getSizeInventory() + { + return fullSize; + } + + @Override + public ItemStack getStackInSlot(int idx) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return io.i.getStackInSlot( idx - io.offset ); + } + return null; + } + + @Override + public ItemStack decrStackSize(int idx, int var2) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return io.i.decrStackSize( idx - io.offset, var2 ); + } + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int idx) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return io.i.getStackInSlotOnClosing( idx - io.offset ); + } + return null; + } + + @Override + public void setInventorySlotContents(int idx, ItemStack var2) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + io.i.setInventorySlotContents( idx - io.offset, var2 ); + } + } + + @Override + public String getInvName() + { + return "ChainedInv"; + } + + @Override + public int getInventoryStackLimit() + { + int smallest = 64; + + for (IInventory i : l) + smallest = Math.min( smallest, i.getInventoryStackLimit() ); + + return smallest; + } + + @Override + public void onInventoryChanged() + { + for (IInventory i : l) + { + i.onInventoryChanged(); + } + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return false; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public boolean isItemValidForSlot(int idx, ItemStack itemstack) + { + InvOffset io = offsets.get( idx ); + if ( io != null ) + { + return io.i.isItemValidForSlot( idx - io.offset, itemstack ); + } + return false; + } +} diff --git a/util/inv/WrapperInventoryRange.java b/util/inv/WrapperInventoryRange.java new file mode 100644 index 00000000..da2abd29 --- /dev/null +++ b/util/inv/WrapperInventoryRange.java @@ -0,0 +1,128 @@ +package appeng.util.inv; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class WrapperInventoryRange implements IInventory +{ + + private IInventory src; + int[] slots; + protected boolean ignoreValidItems = false; + + public static String concateLines(int[] s, String separator) + { + if ( s.length > 0 ) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length; i++) + { + if ( sb.length() > 0 ) + sb.append( separator ); + sb.append( s[i] ); + } + return sb.toString(); + } + return ""; + } + + public WrapperInventoryRange(IInventory a, int[] s, boolean ignoreValid) { + src = a; + slots = s; + if ( slots == null ) + slots = new int[0]; + + ignoreValidItems = ignoreValid; + } + + public WrapperInventoryRange(IInventory a, int _min, int _size, boolean ignoreValid) { + src = a; + slots = new int[_size]; + for (int x = 0; x < _size; x++) + slots[x] = _min + x; + ignoreValidItems = ignoreValid; + } + + @Override + public int getSizeInventory() + { + return slots.length; + } + + @Override + public ItemStack getStackInSlot(int var1) + { + return src.getStackInSlot( slots[var1] ); + } + + @Override + public ItemStack decrStackSize(int var1, int var2) + { + return src.decrStackSize( slots[var1], var2 ); + } + + @Override + public ItemStack getStackInSlotOnClosing(int var1) + { + return src.getStackInSlotOnClosing( slots[var1] ); + } + + @Override + public void setInventorySlotContents(int var1, ItemStack var2) + { + src.setInventorySlotContents( slots[var1], var2 ); + } + + @Override + public String getInvName() + { + return src.getInvName(); + } + + @Override + public int getInventoryStackLimit() + { + return src.getInventoryStackLimit(); + } + + @Override + public void onInventoryChanged() + { + src.onInventoryChanged(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return src.isUseableByPlayer( var1 ); + } + + @Override + public void openChest() + { + src.openChest(); + } + + @Override + public void closeChest() + { + src.closeChest(); + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + if ( ignoreValidItems ) + return true; + + return src.isItemValidForSlot( slots[i], itemstack ); + } + +} diff --git a/util/inv/WrapperMCISidedInventory.java b/util/inv/WrapperMCISidedInventory.java new file mode 100644 index 00000000..49124eb1 --- /dev/null +++ b/util/inv/WrapperMCISidedInventory.java @@ -0,0 +1,50 @@ +package appeng.util.inv; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeDirection; + +public class WrapperMCISidedInventory extends WrapperInventoryRange implements IInventory, IInventoryWrapper +{ + + private ForgeDirection dir; + ISidedInventory side; + + public WrapperMCISidedInventory(ISidedInventory a, ForgeDirection d) { + super( a, a.getAccessibleSlotsFromSide( d.ordinal() ), false ); + side = a; + dir = d; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + + if ( ignoreValidItems ) + return true; + + if ( side.isItemValidForSlot( slots[i], itemstack ) ) + return side.canInsertItem( slots[i], itemstack, dir.ordinal() ); + + return false; + } + + @Override + public boolean canRemoveItemFromSlot(int i, ItemStack is) + { + if ( is == null ) + return false; + + return side.canExtractItem( slots[i], is, dir.ordinal() ); + } + + @Override + public ItemStack decrStackSize(int var1, int var2) + { + if ( canRemoveItemFromSlot( var1, getStackInSlot( var1 ) ) ) + return super.decrStackSize( var1, var2 ); + return null; + } + +} diff --git a/util/inv/WrapperPipe.java b/util/inv/WrapperPipe.java new file mode 100644 index 00000000..ca5541a6 --- /dev/null +++ b/util/inv/WrapperPipe.java @@ -0,0 +1,99 @@ +package appeng.util.inv; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import appeng.integration.modules.BC; + +public class WrapperPipe implements IInventory +{ + + TileEntity ad; + ForgeDirection dir; + + public WrapperPipe(TileEntity te, ForgeDirection d) { + ad = te; + dir = d; + } + + @Override + public int getSizeInventory() + { + return 1; + } + + @Override + public ItemStack getStackInSlot(int i) + { + return null; + } + + @Override + public ItemStack decrStackSize(int i, int j) + { + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int i) + { + return null; + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemstack) + { + BC.instance.addItemsToPipe( ad, itemstack, dir ); + } + + @Override + public String getInvName() + { + return null; + } + + @Override + public boolean isInvNameLocalized() + { + return false; + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public void onInventoryChanged() + { + + } + + @Override + public boolean isUseableByPlayer(EntityPlayer entityplayer) + { + return false; + } + + @Override + public void openChest() + { + + } + + @Override + public void closeChest() + { + + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return BC.instance.canAddItemsToPipe( ad, itemstack, dir ); + } + +} diff --git a/util/item/AEFluidStack.java b/util/item/AEFluidStack.java new file mode 100644 index 00000000..56818126 --- /dev/null +++ b/util/item/AEFluidStack.java @@ -0,0 +1,319 @@ +package appeng.util.item; + +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagString; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import appeng.api.config.FuzzyMode; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAETagCompound; +import appeng.util.Platform; + +import com.google.common.io.ByteStreams; + +public final class AEFluidStack extends AEStack implements IAEFluidStack, Comparable +{ + + public int myHash; + Fluid fluid; + protected IAETagCompound tagCompound; + + @Override + public IAETagCompound getTagCompound() + { + return tagCompound; + } + + @Override + public void add(IAEFluidStack option) + { + if ( option == null ) + return; + + // if ( priority < ((AEFluidStack) option).priority ) + // priority = ((AEFluidStack) option).priority; + + incStackSize( option.getStackSize() ); + setCountRequestable( getCountRequestable() + option.getCountRequestable() ); + setCraftable( isCraftable() || option.isCraftable() ); + } + + private AEFluidStack(AEFluidStack is) { + stackSize = is.stackSize; + // priority = is.priority; + setCraftable( is.isCraftable() ); + setCountRequestable( is.getCountRequestable() ); + + this.myHash = is.myHash; + } + + protected AEFluidStack(FluidStack is) { + if ( is == null ) + throw new RuntimeException( "Invalid Itemstack." ); + + fluid = is.getFluid(); + stackSize = is.amount; + setCraftable( false ); + setCountRequestable( 0 ); + + myHash = fluid.hashCode() ^ (tagCompound == null ? 0 : System.identityHashCode( tagCompound )); + } + + public static AEFluidStack create(Object a) + { + if ( a == null ) + return null; + if ( a instanceof AEFluidStack ) + ((AEFluidStack) a).copy(); + if ( a instanceof FluidStack ) + return new AEFluidStack( (FluidStack) a ); + return null; + } + + @Override + public boolean equals(Object ia) + { + if ( ia instanceof AEFluidStack ) + { + return ((AEFluidStack) ia).fluid == fluid && tagCompound == ((AEFluidStack) ia).tagCompound; + } + else if ( ia instanceof FluidStack ) + { + FluidStack is = (FluidStack) ia; + + if ( is.fluidID == this.fluid.getID() ) + { + NBTTagCompound ta = (NBTTagCompound) tagCompound; + NBTTagCompound tb = is.tag; + if ( ta == tb ) + return true; + + 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()) ) + return true; + + if ( (ta == null && tb != null) || (ta != null && tb == null) ) + return false; + + if ( AESharedNBT.isShared( tb ) ) + return ta == tb; + + return Platform.NBTEqualityTest( ta, tb ); + } + } + return false; + } + + @Override + public FluidStack getFluidStack() + { + FluidStack is = new FluidStack( fluid, (int) Math.min( Integer.MAX_VALUE, stackSize ) ); + if ( tagCompound != null ) + is.tag = tagCompound.getNBTTagCompoundCopy(); + + return is; + } + + @Override + public IAEFluidStack copy() + { + return new AEFluidStack( this ); + } + + @Override + public void writeToNBT(NBTTagCompound i) + { + /* + * Ugly Yes, but it saves a lot in the memory department. + */ + + NBTBase FluidName = i.getTag( "FluidName" ); + NBTBase Count = i.getTag( "Count" ); + // NBTBase Priority = i.getTag( "Priority" ); + NBTBase Cnt = i.getTag( "Cnt" ); + NBTBase Req = i.getTag( "Req" ); + NBTBase Craft = i.getTag( "Craft" ); + + if ( FluidName != null && FluidName instanceof NBTTagString ) + ((NBTTagString) FluidName).data = (String) this.fluid.getName(); + else + i.setString( "FluidName", (String) this.fluid.getName() ); + + // if ( Priority != null && Priority instanceof NBTTagInt ) + // ((NBTTagInt) Priority).data = this.priority; + // else + // i.setInteger( "Priority", this.priority ); + + if ( Count != null && Count instanceof NBTTagByte ) + ((NBTTagByte) Count).data = (byte) 0; + else + i.setByte( "Count", (byte) 0 ); + + if ( Cnt != null && Cnt instanceof NBTTagLong ) + ((NBTTagLong) Cnt).data = this.stackSize; + else + i.setLong( "Cnt", this.stackSize ); + + if ( Req != null && Req instanceof NBTTagLong ) + ((NBTTagLong) Req).data = this.stackSize; + else + i.setLong( "Req", this.getCountRequestable() ); + + if ( Craft != null && Craft instanceof NBTTagByte ) + ((NBTTagByte) Craft).data = (byte) (this.isCraftable() ? 1 : 0); + else + i.setBoolean( "Craft", this.isCraftable() ); + + if ( tagCompound != null ) + i.setTag( "tag", (NBTTagCompound) tagCompound ); + else + i.removeTag( "tag" ); + + } + + public static IAEFluidStack loadFluidStackFromNBT(NBTTagCompound i) + { + ItemStack itemstack = ItemStack.loadItemStackFromNBT( i ); + if ( itemstack == null ) + return null; + AEFluidStack aeis = AEFluidStack.create( itemstack ); + // aeis.priority = i.getInteger( "Priority" ); + aeis.stackSize = i.getLong( "Cnt" ); + aeis.setCountRequestable( i.getLong( "Req" ) ); + aeis.setCraftable( i.getBoolean( "Craft" ) ); + return aeis; + } + + @Override + public boolean hasTagCompound() + { + return tagCompound != null; + } + + @Override + public int hashCode() + { + return myHash; + } + + @Override + public int compareTo(AEFluidStack b) + { + int diff = hashCode() - b.hashCode(); + return diff > 0 ? 1 : (diff < 0 ? -1 : 0); + } + + @Override + void writeIdentity(DataOutputStream i) throws IOException + { + byte[] name = fluid.getName().getBytes( "UTF-8" ); + i.writeByte( (byte) name.length ); + i.write( name ); + } + + @Override + void readNBT(DataOutputStream i) throws IOException + { + if ( hasTagCompound() ) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + CompressedStreamTools.write( (NBTTagCompound) getTagCompound(), data ); + + byte[] tagBytes = bytes.toByteArray(); + int size = tagBytes.length; + + i.writeInt( size ); + i.write( tagBytes ); + } + } + + public static IAEFluidStack loadItemStackFromPacket(DataInputStream data) throws IOException + { + byte mask = data.readByte(); + // byte PriorityType = (byte) (mask & 0x03); + byte StackType = (byte) ((mask & 0x0C) >> 2); + byte CountReqType = (byte) ((mask & 0x30) >> 4); + boolean isCraftable = (mask & 0x40) > 0; + boolean hasTagCompound = (mask & 0x80) > 0; + + // don't send this... + NBTTagCompound d = new NBTTagCompound(); + + byte len2 = data.readByte(); + byte name[] = new byte[len2]; + data.read( name, 0, len2 ); + + d.setString( "FluidName", new String( name, "UTF-8" ) ); + d.setByte( "Count", (byte) 0 ); + + if ( hasTagCompound ) + { + int len = data.readInt(); + + byte[] bd = new byte[len]; + data.readFully( bd ); + + DataInput di = ByteStreams.newDataInput( bd ); + d.setCompoundTag( "tag", CompressedStreamTools.read( di ) ); + } + + // long priority = getPacketValue( PriorityType, data ); + long stackSize = getPacketValue( StackType, data ); + long countRequestable = getPacketValue( CountReqType, data ); + + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d ); + if ( fluidStack == null ) + return null; + + AEFluidStack aeis = AEFluidStack.create( fluidStack ); + // aeis.priority = (int) priority; + aeis.stackSize = stackSize; + aeis.setCountRequestable( countRequestable ); + aeis.setCraftable( isCraftable ); + return aeis; + } + + @Override + public Fluid getFluid() + { + return fluid; + } + + @Override + public IAEFluidStack empty() + { + IAEFluidStack dup = copy(); + dup.reset(); + return dup; + } + + @Override + public boolean fuzzyComparison(Object st, FuzzyMode mode) + { + if ( st instanceof FluidStack ) + { + return ((FluidStack) st).getFluid() == getFluid(); + } + + if ( st instanceof IAEFluidStack ) + { + return ((IAEFluidStack) st).getFluid() == getFluid(); + } + + return false; + } + +} diff --git a/util/item/AEItemDef.java b/util/item/AEItemDef.java new file mode 100644 index 00000000..efa0886c --- /dev/null +++ b/util/item/AEItemDef.java @@ -0,0 +1,41 @@ +package appeng.util.item; + +import java.util.List; + +import net.minecraft.item.Item; +import appeng.api.storage.data.IAETagCompound; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class AEItemDef +{ + + public int myHash; + + public int def; + + public Item item; + public int damageValue; + + public int dspDamage; + public int maxDamage; + + public IAETagCompound tagCompound; + + @SideOnly(Side.CLIENT) + public String displayName; + + @SideOnly(Side.CLIENT) + public List tooltip; + + public AEItemDef copy() + { + AEItemDef t = new AEItemDef(); + t.def = def; + t.item = item; + t.damageValue = damageValue; + t.dspDamage = dspDamage; + t.maxDamage = maxDamage; + return t; + } +} diff --git a/util/item/AEItemStack.java b/util/item/AEItemStack.java new file mode 100644 index 00000000..f9596115 --- /dev/null +++ b/util/item/AEItemStack.java @@ -0,0 +1,499 @@ +package appeng.util.item; + +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagShort; +import appeng.api.config.FuzzyMode; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAETagCompound; +import appeng.util.Platform; + +import com.google.common.io.ByteStreams; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public final class AEItemStack extends AEStack implements IAEItemStack, Comparable +{ + + AEItemDef def; + + @Override + public void add(IAEItemStack option) + { + if ( option == null ) + return; + + // if ( priority < ((AEItemStack) option).priority ) + // priority = ((AEItemStack) option).priority; + + incStackSize( option.getStackSize() ); + setCountRequestable( getCountRequestable() + option.getCountRequestable() ); + setCraftable( isCraftable() || option.isCraftable() ); + } + + private AEItemStack(AEItemStack is) { + def = is.def; + stackSize = is.stackSize; + setCraftable( is.isCraftable() ); + setCountRequestable( is.getCountRequestable() ); + } + + protected AEItemStack(ItemStack is) { + if ( is == null ) + throw new RuntimeException( "Invalid Itemstack." ); + + def = new AEItemDef(); + def.item = is.getItem(); + + /* + * Prevent an Item from changing the damage value on me... Either, this or a core mod. + */ + + /* + * Super Hacky. + * + * is.itemID = appeng.api.Materials.matQuartz.itemID; damageValue = is.getItemDamage(); is.itemID = itemID; + */ + + /* + * Kinda Hacky + */ + def.damageValue = Item.blazeRod.getDamage( is ); + def.def = is.itemID << Platform.DEF_OFFSET | def.damageValue; + + def.dspDamage = is.getItemDamageForDisplay(); + def.maxDamage = is.getMaxDamage(); + + def.tagCompound = (IAETagCompound) AESharedNBT.getSharedTagCompound( is ); + + stackSize = is.stackSize; + setCraftable( false ); + setCountRequestable( 0 ); + + def.myHash = def.def ^ (def.tagCompound == null ? 0 : System.identityHashCode( def.tagCompound )); + } + + public static AEItemStack create(Object a) + { + if ( a == null ) + return null; + if ( a instanceof IAEItemStack ) + ((IAEItemStack) a).copy(); + if ( a instanceof ItemStack ) + return new AEItemStack( (ItemStack) a ); + return null; + } + + @Override + public Item getItem() + { + return def.item; + } + + @Override + public boolean equals(Object ia) + { + if ( ia instanceof AEItemStack ) + { + return ((AEItemStack) ia).def == def && def.tagCompound == ((AEItemStack) ia).def.tagCompound; + } + else if ( ia instanceof ItemStack ) + { + ItemStack is = (ItemStack) ia; + + if ( is.getItem() == def.item && is.getItemDamage() == this.def.damageValue ) + { + NBTTagCompound ta = (NBTTagCompound) def.tagCompound; + NBTTagCompound tb = is.getTagCompound(); + if ( ta == tb ) + return true; + + 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()) ) + return true; + + if ( (ta == null && tb != null) || (ta != null && tb == null) ) + return false; + + if ( AESharedNBT.isShared( tb ) ) + return ta == tb; + + return Platform.NBTEqualityTest( ta, tb ); + } + } + return false; + } + + @Override + public ItemStack getItemStack() + { + ItemStack is = new ItemStack( def.item, (int) Math.min( Integer.MAX_VALUE, stackSize ), def.damageValue ); + if ( def.tagCompound != null ) + is.setTagCompound( def.tagCompound.getNBTTagCompoundCopy() ); + + return is; + } + + @Override + public IAEItemStack copy() + { + return new AEItemStack( this ); + } + + @Override + public void writeToNBT(NBTTagCompound i) + { + /* + * Ugly Yes, but it saves a lot in the memory department. + */ + + NBTBase id = i.getTag( "id" ); + NBTBase Count = i.getTag( "Count" ); + // NBTBase Priority = i.getTag( "Priority" ); + NBTBase Cnt = i.getTag( "Cnt" ); + NBTBase Req = i.getTag( "Req" ); + NBTBase Craft = i.getTag( "Craft" ); + NBTBase Damage = i.getTag( "Damage" ); + + if ( id != null && id instanceof NBTTagShort ) + ((NBTTagShort) id).data = (short) this.def.item.itemID; + else + i.setShort( "id", (short) this.def.item.itemID ); + + // if ( Priority != null && Priority instanceof NBTTagInt ) + // ((NBTTagInt) Priority).data = this.priority; + // else + // i.setInteger( "Priority", this.priority ); + + if ( Count != null && Count instanceof NBTTagByte ) + ((NBTTagByte) Count).data = (byte) 0; + else + i.setByte( "Count", (byte) 0 ); + + if ( Cnt != null && Cnt instanceof NBTTagLong ) + ((NBTTagLong) Cnt).data = this.stackSize; + else + i.setLong( "Cnt", this.stackSize ); + + if ( Req != null && Req instanceof NBTTagLong ) + ((NBTTagLong) Req).data = this.stackSize; + else + i.setLong( "Req", this.getCountRequestable() ); + + if ( Craft != null && Craft instanceof NBTTagByte ) + ((NBTTagByte) Craft).data = (byte) (this.isCraftable() ? 1 : 0); + else + i.setBoolean( "Craft", this.isCraftable() ); + + if ( Damage != null && Damage instanceof NBTTagShort ) + ((NBTTagShort) Damage).data = (short) this.def.damageValue; + else + i.setShort( "Damage", (short) this.def.damageValue ); + + if ( def.tagCompound != null ) + i.setTag( "tag", (NBTTagCompound) def.tagCompound ); + else + i.removeTag( "tag" ); + + } + + public static IAEItemStack loadItemStackFromNBT(NBTTagCompound i) + { + ItemStack itemstack = ItemStack.loadItemStackFromNBT( i ); + if ( itemstack == null ) + return null; + AEItemStack aeis = AEItemStack.create( itemstack ); + // aeis.priority = i.getInteger( "Priority" ); + aeis.stackSize = i.getLong( "Cnt" ); + aeis.setCountRequestable( i.getLong( "Req" ) ); + aeis.setCraftable( i.getBoolean( "Craft" ) ); + return aeis; + } + + @Override + public boolean hasTagCompound() + { + return def.tagCompound != null; + } + + @Override + public int hashCode() + { + return def.myHash; + } + + @Override + public int compareTo(AEItemStack b) + { + int id = def.item.itemID - b.def.item.itemID; + int dv = def.damageValue - b.def.damageValue; + int dspv = def.dspDamage - b.def.dspDamage; + + return id == 0 ? (dv == 0 ? (dspv == 0 ? ((def.tagCompound == null ? 0 : def.tagCompound.hashCode()) - (b.def.tagCompound == null ? 0 + : b.def.tagCompound.hashCode())) : dspv) : dv) : id; + } + + @SideOnly(Side.CLIENT) + public List getToolTip() + { + if ( def.tooltip != null ) + return def.tooltip; + + return def.tooltip = Platform.getTooltip( getItemStack() ); + } + + @SideOnly(Side.CLIENT) + public String getDisplayName() + { + if ( def.displayName != null ) + return def.displayName; + + return def.displayName = Platform.getItemDisplayName( getItemStack() ); + } + + @Override + public IAEItemStack empty() + { + IAEItemStack dup = copy(); + dup.reset(); + return dup; + } + + @Override + public int getItemDamage() + { + return def.damageValue; + } + + @Override + void writeIdentity(DataOutputStream i) throws IOException + { + i.writeShort( def.item.itemID ); + i.writeShort( getItemDamage() ); + } + + @Override + void readNBT(DataOutputStream i) throws IOException + { + if ( hasTagCompound() ) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream( bytes ); + + CompressedStreamTools.write( (NBTTagCompound) getTagCompound(), data ); + + byte[] tagBytes = bytes.toByteArray(); + int size = tagBytes.length; + + i.writeInt( size ); + i.write( tagBytes ); + } + } + + public static IAEItemStack loadItemStackFromPacket(DataInputStream data) throws IOException + { + byte mask = data.readByte(); + // byte PriorityType = (byte) (mask & 0x03); + byte StackType = (byte) ((mask & 0x0C) >> 2); + byte CountReqType = (byte) ((mask & 0x30) >> 4); + boolean isCraftable = (mask & 0x40) > 0; + boolean hasTagCompound = (mask & 0x80) > 0; + + // don't send this... + NBTTagCompound d = new NBTTagCompound(); + + d.setShort( "id", data.readShort() ); + d.setShort( "Damage", data.readShort() ); + d.setByte( "Count", (byte) 0 ); + + if ( hasTagCompound ) + { + int len = data.readInt(); + + byte[] bd = new byte[len]; + data.readFully( bd ); + + DataInput di = ByteStreams.newDataInput( bd ); + d.setCompoundTag( "tag", CompressedStreamTools.read( di ) ); + } + + // long priority = getPacketValue( PriorityType, data ); + long stackSize = getPacketValue( StackType, data ); + long countRequestable = getPacketValue( CountReqType, data ); + + ItemStack itemstack = ItemStack.loadItemStackFromNBT( d ); + if ( itemstack == null ) + return null; + + AEItemStack aeis = AEItemStack.create( itemstack ); + // aeis.priority = (int) priority; + aeis.stackSize = stackSize; + aeis.setCountRequestable( countRequestable ); + aeis.setCraftable( isCraftable ); + return aeis; + } + + @Override + public boolean sameOre(IAEItemStack is) + { + return OreHelper.instance.sameOre( this, is ); + } + + @Override + public boolean fuzzyComparison(Object st, FuzzyMode Mode) + { + if ( st instanceof IAEItemStack ) + { + IAEItemStack o = (IAEItemStack) st; + + if ( sameOre( o ) ) + return true; + + if ( o.getItem() == getItem() ) + { + if ( def.item.isDamageable() ) + { + ItemStack a = getItemStack(); + ItemStack b = o.getItemStack(); + + try + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); + } + else + { + float APercentDamaged = 1.0f - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); + float BPercentDamaged = 1.0f - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + catch (Throwable e) + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); + } + else + { + float APercentDamaged = (float) a.getItemDamage() / (float) a.getMaxDamage(); + float BPercentDamaged = (float) b.getItemDamage() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + } + + return this.getItemDamage() == o.getItemDamage(); + } + } + + if ( st instanceof ItemStack ) + { + ItemStack o = (ItemStack) st; + + OreHelper.instance.sameOre( this, o ); + + if ( o.getItem() == getItem() ) + { + if ( def.item.isDamageable() ) + { + ItemStack a = getItemStack(); + ItemStack b = o; + + try + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); + } + else + { + float APercentDamaged = 1.0f - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); + float BPercentDamaged = 1.0f - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + catch (Throwable e) + { + if ( Mode == FuzzyMode.IGNORE_ALL ) + { + return true; + } + else if ( Mode == FuzzyMode.PERCENT_99 ) + { + return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); + } + else + { + float APercentDamaged = (float) a.getItemDamage() / (float) a.getMaxDamage(); + float BPercentDamaged = (float) b.getItemDamage() / (float) b.getMaxDamage(); + + return (APercentDamaged > Mode.breakPoint) == (BPercentDamaged > Mode.breakPoint); + } + } + } + + return this.getItemDamage() == o.getItemDamage(); + } + } + + return false; + } + + public IAEItemStack getLow(FuzzyMode fuzzy) + { + AEItemStack bottom = new AEItemStack( this ); + bottom.def = bottom.def.copy(); + + int low = fuzzy.calculateBreakPoint( def.maxDamage ); + bottom.def.dspDamage = low < def.dspDamage ? low : 0; + + return bottom; + } + + public IAEItemStack getHigh(FuzzyMode fuzzy) + { + AEItemStack top = new AEItemStack( this ); + top.def = top.def.copy(); + + int high = fuzzy.calculateBreakPoint( def.maxDamage ); + top.def.dspDamage = high > def.dspDamage ? high : def.maxDamage; + + return top; + } + + @Override + public IAETagCompound getTagCompound() + { + return def.tagCompound; + } +} diff --git a/util/item/AESharedNBT.java b/util/item/AESharedNBT.java new file mode 100644 index 00000000..f42f9308 --- /dev/null +++ b/util/item/AESharedNBT.java @@ -0,0 +1,172 @@ +package appeng.util.item; + +import java.lang.ref.WeakReference; +import java.util.Iterator; +import java.util.WeakHashMap; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import appeng.api.AEApi; +import appeng.api.features.IItemComparison; +import appeng.api.storage.data.IAETagCompound; +import appeng.util.Platform; + +/* + * this is used for the shared NBT Cache. + */ +public class AESharedNBT extends NBTTagCompound implements IAETagCompound +{ + + private int itemid, meta, hash; + public SharedSearchObject sso; + private IItemComparison comp; + + @Override + public IItemComparison getSpecialComparison() + { + return comp; + } + + private AESharedNBT(int itemID, int damageValue, String name) { + super( name ); + itemid = itemID; + meta = damageValue; + } + + @Override + public NBTTagCompound getNBTTagCompoundCopy() + { + return (NBTTagCompound) copy(); + } + + public static AESharedNBT createFromCompound(int itemID, int damageValue, NBTTagCompound c) + { + AESharedNBT x = new AESharedNBT( itemID, damageValue, c.getName() ); + + Iterator var2 = c.getTags().iterator(); + + while (var2.hasNext()) + { + NBTBase tag = (NBTBase) var2.next(); + x.setTag( tag.getName(), (NBTBase) tag.copy() ); + } + + x.hash = Platform.NBTOrderlessHash( c ); + + ItemStack isc = new ItemStack( itemID, 1, damageValue ); + isc.setTagCompound( c ); + x.comp = AEApi.instance().registries().specialComparson().getSpecialComparion( isc ); + + return x; + } + + @Override + public boolean equals(Object par1Obj) + { + if ( par1Obj instanceof AESharedNBT ) + return this == par1Obj; + return super.equals( par1Obj ); + } + + public boolean matches(int itemid2, int meta2, int orderlessHash) + { + return itemid2 == itemid && meta == meta2 && hash == orderlessHash; + } + + public boolean comparePreciseWithRegistry(AESharedNBT tagCompound) + { + if ( this == tagCompound ) + return true; + + if ( comp != null && tagCompound.comp != null ) + { + return comp.sameAsPrecise( tagCompound.comp ); + } + + return false; + } + + public boolean compareFuzzyWithRegistry(AESharedNBT tagCompound) + { + if ( this == tagCompound ) + return true; + if ( tagCompound == null ) + return false; + + if ( comp == tagCompound.comp ) + return true; + + if ( comp != null ) + { + return comp.sameAsFuzzy( tagCompound.comp ); + } + + return false; + } + + /* + * Shared Tag Compound Cache. + */ + private static WeakHashMap> sharedTagCompounts = new WeakHashMap(); + + /* + * Debug purposes. + */ + public static int sharedTagLoad() + { + return sharedTagCompounts.size(); + } + + /* + * returns true if the compound is part of the shared compound system ( and can thus be compared directly ). + */ + public static boolean isShared(NBTTagCompound ta) + { + return ta instanceof AESharedNBT; + } + + /* + * Returns an NBT Compound that is used for accelerating comparisons. + */ + synchronized public static NBTTagCompound getSharedTagCompound(ItemStack s) + { + NBTTagCompound tagCompound = s.getTagCompound(); + if ( tagCompound == null ) + return null; + if ( tagCompound.hasNoTags() ) + return null; + + int itemid = s.itemID; + int meta = -1; + if ( s.itemID != 0 && s.isItemStackDamageable() && s.getHasSubtypes() ) + meta = s.getItemDamage(); + + if ( isShared( tagCompound ) ) + return tagCompound; + + SharedSearchObject sso = new SharedSearchObject( itemid, meta, tagCompound ); + + WeakReference c = sharedTagCompounts.get( sso ); + if ( c != null ) + { + SharedSearchObject cg = c.get(); + if ( cg != null ) + return cg.shared; // I don't think I really need to check this + // as its already certain to exist.. + } + + AESharedNBT clone = AESharedNBT.createFromCompound( itemid, meta, tagCompound ); + sso.compound = (NBTTagCompound) sso.compound.copy(); // prevent + // modification + // of data based + // on original + // item. + sso.shared = clone; + clone.sso = sso; + + sharedTagCompounts.put( sso, new WeakReference( sso ) ); + return clone; + } + +} diff --git a/util/item/AEStack.java b/util/item/AEStack.java new file mode 100644 index 00000000..1872bce7 --- /dev/null +++ b/util/item/AEStack.java @@ -0,0 +1,165 @@ +package appeng.util.item; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import appeng.api.storage.data.IAEStack; + +public abstract class AEStack implements IAEStack +{ + + protected boolean isCraftable; + protected long stackSize; + protected long countRequestable; + + @Override + public boolean isMeaninful() + { + return stackSize != 0 || getCountRequestable() > 0 || isCraftable(); + } + + @Override + public StackType reset() + { + stackSize = 0; + // priority = Integer.MIN_VALUE; + setCountRequestable( 0 ); + setCraftable( false ); + return (StackType) this; + } + + @Override + public long getStackSize() + { + return stackSize; + } + + @Override + public StackType setStackSize(long ss) + { + stackSize = ss; + return (StackType) this; + } + + @Override + public long getCountRequestable() + { + return countRequestable; + } + + @Override + public StackType setCountRequestable(long countRequestable) + { + this.countRequestable = countRequestable; + return (StackType) this; + } + + @Override + public boolean isCraftable() + { + return isCraftable; + } + + @Override + public StackType setCraftable(boolean isCraftable) + { + this.isCraftable = isCraftable; + return (StackType) this; + } + + @Override + public void decStackSize(long i) + { + stackSize -= i; + } + + @Override + public void incStackSize(long i) + { + stackSize += i; + } + + @Override + public void decCountRequestable(long i) + { + countRequestable -= i; + } + + @Override + public void incCountRequestable(long i) + { + countRequestable += i; + } + + void putPacketValue(DataOutputStream tag, long num) throws IOException + { + if ( num <= 255 ) + tag.writeByte( (byte) (num + (long) Byte.MIN_VALUE) ); + else if ( num <= 65535 ) + tag.writeShort( (short) (num + (long) Short.MIN_VALUE) ); + else if ( num <= 4294967295L ) + tag.writeInt( (int) (num + (long) Integer.MIN_VALUE) ); + else + tag.writeLong( num ); + } + + static long getPacketValue(byte type, DataInputStream tag) throws IOException + { + if ( type == 0 ) + { + long l = tag.readByte(); + l -= (long) Byte.MIN_VALUE; + return l; + } + else if ( type == 1 ) + { + long l = tag.readShort(); + l -= (long) Short.MIN_VALUE; + return l; + } + else if ( type == 2 ) + { + long l = tag.readInt(); + l -= (long) Integer.MIN_VALUE; + return l; + } + + return tag.readLong(); + } + + byte getType(long num) + { + if ( num <= 255 ) + return 0; + else if ( num <= 65535 ) + return 1; + else if ( num <= 4294967295L ) + return 2; + else + return 3; + } + + abstract void writeIdentity(DataOutputStream i) throws IOException; + + abstract void readNBT(DataOutputStream i) throws IOException; + + abstract boolean hasTagCompound(); + + @Override + public void writeToPacket(DataOutputStream i) throws IOException + { + byte mask = (byte) (getType( 0 ) | (getType( stackSize ) << 2) | (getType( getCountRequestable() ) << 4) | ((byte) (isCraftable ? 1 : 0) << 6) | (hasTagCompound() ? 1 + : 0) << 7); + + i.writeByte( mask ); + writeIdentity( i ); + + readNBT( i ); + + // putPacketValue( i, priority ); + putPacketValue( i, stackSize ); + putPacketValue( i, getCountRequestable() ); + } + +} diff --git a/util/item/ItemList.java b/util/item/ItemList.java new file mode 100644 index 00000000..6ca1502a --- /dev/null +++ b/util/item/ItemList.java @@ -0,0 +1,187 @@ +package appeng.util.item; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; + +import appeng.api.config.FuzzyMode; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +public final class ItemList implements IItemList +{ + + private final TreeMap records = new TreeMap(); + // private int currentPriority = Integer.MIN_VALUE; + + int iteration = Integer.MIN_VALUE; + public Throwable stacktrace; + + @Override + synchronized public void add(StackType option) + { + if ( option == null ) + return; + + StackType st = records.get( option ); + + if ( st != null ) + { + // st.setPriority( currentPriority ); + st.add( option ); + return; + } + + StackType opt = (StackType) option.copy(); + // opt.setPriority( currentPriority ); + records.put( opt, opt ); + } + + @Override + synchronized public void addStorage(StackType option) // adds a stack as + // stored. + { + if ( option == null ) + return; + + StackType st = records.get( option ); + + if ( st != null ) + { + // st.setPriority( currentPriority ); + st.incStackSize( option.getStackSize() ); + return; + } + + StackType opt = (StackType) option.copy(); + // opt.setPriority( currentPriority ); + records.put( opt, opt ); + } + + @Override + synchronized public void addCrafting(StackType option) // adds a stack as + // craftable. + { + if ( option == null ) + return; + + StackType st = records.get( option ); + + if ( st != null ) + { + // st.setPriority( currentPriority ); + st.setCraftable( true ); + return; + } + + StackType opt = (StackType) option.copy(); + // opt.setPriority( currentPriority ); + opt.setStackSize( 0 ); + opt.setCraftable( true ); + + records.put( opt, opt ); + } + + @Override + synchronized public void addRequestable(StackType option) // adds a stack + // as + // requestable. + { + if ( option == null ) + return; + + StackType st = records.get( option ); + + if ( st != null ) + { + // st.setPriority( currentPriority ); + ((IAEItemStack) st).setCountRequestable( ((IAEItemStack) st).getCountRequestable() + ((IAEItemStack) option).getCountRequestable() ); + return; + } + + StackType opt = (StackType) option.copy(); + // opt.setPriority( currentPriority ); + opt.setStackSize( 0 ); + opt.setCraftable( false ); + opt.setCountRequestable( opt.getCountRequestable() ); + + records.put( opt, opt ); + } + + @Override + synchronized public StackType getFirstItem() + { + Iterator i = this.iterator(); + while (i.hasNext()) + return i.next(); + return null; + } + + @Override + synchronized public void resetStatus() + { + for (StackType i : this) + i.reset(); + } + + /* + * synchronized public void clean() { Iterator i = iterator(); while (i.hasNext()) { StackType AEI = + * i.next(); if ( !AEI.isMeaninful() ) i.remove(); } } + */ + + @Override + synchronized public Iterator iterator() + { + return new MeanfulIterator( records.values().iterator() ); + } + + @Override + synchronized public StackType findPrecise(StackType i) + { + if ( i == null ) + return null; + + StackType is = records.get( i ); + if ( is != null ) + { + return is; + } + + return null; + } + + @Override + synchronized public int size() + { + return records.values().size(); + } + + @Override + public boolean isEmpty() + { + return records.isEmpty(); + } + + @Override + public Collection findFuzzy(StackType filter, FuzzyMode fuzzy) + { + if ( filter instanceof IAEFluidStack ) + return filter.equals( this ) ? (List) Arrays.asList( new IAEFluidStack[] { (IAEFluidStack) filter } ) : (List) Arrays + .asList( new IAEFluidStack[] {} ); + + AEItemStack ais = (AEItemStack) filter; + + if ( OreHelper.instance.isOre( ais ) ) + { + + } + + StackType low = (StackType) ais.getLow( fuzzy ); + StackType high = (StackType) ais.getHigh( fuzzy ); + return records.subMap( low, high ).values(); + } +} diff --git a/util/item/MeanfulIterator.java b/util/item/MeanfulIterator.java new file mode 100644 index 00000000..671583ee --- /dev/null +++ b/util/item/MeanfulIterator.java @@ -0,0 +1,44 @@ +package appeng.util.item; + +import java.util.Iterator; + +import appeng.api.storage.data.IAEStack; + +public class MeanfulIterator implements Iterator +{ + + final Iterator parent; + private StackType next; + + public MeanfulIterator(Iterator iterator) { + parent = iterator; + } + + @Override + public boolean hasNext() + { + while (parent.hasNext()) + { + next = parent.next(); + if ( next.isMeaninful() ) + return true; + else + parent.remove(); // self cleaning :3 + } + + return false; + } + + @Override + public Object next() + { + return next; + } + + @Override + public void remove() + { + parent.remove(); + } + +} diff --git a/util/item/OreHelper.java b/util/item/OreHelper.java new file mode 100644 index 00000000..72f2bf3c --- /dev/null +++ b/util/item/OreHelper.java @@ -0,0 +1,29 @@ +package appeng.util.item; + +import net.minecraft.item.ItemStack; +import appeng.api.storage.data.IAEItemStack; + +public class OreHelper +{ + + public static OreHelper instance; + + public boolean isOre(IAEItemStack is) + { + // TODO Auto-generated method stub + return false; + } + + public boolean sameOre(AEItemStack aeItemStack, IAEItemStack is) + { + // TODO Auto-generated method stub + return false; + } + + public void sameOre(AEItemStack aeItemStack, ItemStack o) + { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff --git a/util/item/SharedSearchObject.java b/util/item/SharedSearchObject.java new file mode 100644 index 00000000..0ee48e89 --- /dev/null +++ b/util/item/SharedSearchObject.java @@ -0,0 +1,39 @@ +package appeng.util.item; + +import appeng.util.Platform; +import net.minecraft.nbt.NBTTagCompound; + +public class SharedSearchObject +{ + + int def; + int hash; + NBTTagCompound compound; + public AESharedNBT shared; + + public SharedSearchObject(int itemID, int damageValue, NBTTagCompound tagCompound) { + def = (damageValue << Platform.DEF_OFFSET) | itemID; + hash = Platform.NBTOrderlessHash( tagCompound ); + compound = tagCompound; + } + + @Override + public boolean equals(Object obj) + { + if ( obj == null ) + return false; + SharedSearchObject b = (SharedSearchObject) obj; + if ( def == b.def && hash == b.hash ) + { + return Platform.NBTEqualityTest( compound, b.compound ); + } + return false; + } + + @Override + public int hashCode() + { + return def ^ hash; + } + +} diff --git a/util/iterators/ChainedIterator.java b/util/iterators/ChainedIterator.java new file mode 100644 index 00000000..c97e6708 --- /dev/null +++ b/util/iterators/ChainedIterator.java @@ -0,0 +1,33 @@ +package appeng.util.iterators; + +import java.util.Iterator; + +public class ChainedIterator implements Iterator +{ + + int offset = 0; + T[] list; + + public ChainedIterator(T... list) { + this.list = list; + } + + @Override + public boolean hasNext() + { + return offset < list.length; + } + + @Override + public T next() + { + return list[offset++]; + } + + @Override + public void remove() + { + throw new RuntimeException( "Not implemented." ); + } + +} diff --git a/util/iterators/NullIterator.java b/util/iterators/NullIterator.java new file mode 100644 index 00000000..3f05975c --- /dev/null +++ b/util/iterators/NullIterator.java @@ -0,0 +1,26 @@ +package appeng.util.iterators; + +import java.util.Iterator; + +public class NullIterator implements Iterator +{ + + @Override + public boolean hasNext() + { + return false; + } + + @Override + public T next() + { + return null; + } + + @Override + public void remove() + { + + } + +} diff --git a/util/iterators/ProxyNodeIterator.java b/util/iterators/ProxyNodeIterator.java new file mode 100644 index 00000000..aaf80cdd --- /dev/null +++ b/util/iterators/ProxyNodeIterator.java @@ -0,0 +1,37 @@ +package appeng.util.iterators; + +import java.util.Iterator; + +import net.minecraftforge.common.ForgeDirection; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; + +public class ProxyNodeIterator implements Iterator +{ + + Iterator hosts; + + public ProxyNodeIterator(Iterator hosts) { + this.hosts = hosts; + } + + @Override + public boolean hasNext() + { + return hosts.hasNext(); + } + + @Override + public IGridNode next() + { + IGridHost host = hosts.next(); + return host.getGridNode( ForgeDirection.UNKNOWN ); + } + + @Override + public void remove() + { + throw new RuntimeException( "Not implemented." ); + } + +} diff --git a/util/iterators/StackToSlotIterator.java b/util/iterators/StackToSlotIterator.java new file mode 100644 index 00000000..32119502 --- /dev/null +++ b/util/iterators/StackToSlotIterator.java @@ -0,0 +1,39 @@ +package appeng.util.iterators; + +import java.util.Iterator; + +import net.minecraft.item.ItemStack; +import appeng.util.inv.ItemSlot; + +public class StackToSlotIterator implements Iterator +{ + + int x = 0; + final ItemSlot iss = new ItemSlot(); + final Iterator is; + + public StackToSlotIterator(Iterator is) { + this.is = is; + } + + @Override + public boolean hasNext() + { + return is.hasNext(); + } + + @Override + public ItemSlot next() + { + iss.slot = x++; + iss.itemStack = is.next(); + return iss; + } + + @Override + public void remove() + { + // uhh no. + } + +} diff --git a/util/math/Helper.java b/util/math/Helper.java new file mode 100644 index 00000000..36aa542c --- /dev/null +++ b/util/math/Helper.java @@ -0,0 +1,30 @@ +package appeng.util.math; + +import org.lwjgl.util.vector.Quaternion; +import org.lwjgl.util.vector.Vector3f; + +public class Helper +{ + + public static final Helper instance = new Helper(); + + public Quaternion getRotation(Vector3f vForward, Vector3f vUp) + { + Vector3f vRight = new Vector3f(); + Vector3f.cross( vUp, vForward, vRight ); + + /* + * vRight.x vRight.y, vRight.z, vUp.x, vUp.y, vUp.z, vForward.x, + * vForward.y, vForward.z + */ + + Quaternion qrot = new Quaternion(); + qrot.w = (float) Math.sqrt( 1.0f + vRight.x + vUp.y + vForward.z ) / 2.0f; + double dfWScale = qrot.w * 4.0; + qrot.x = (float) ((vForward.y - vUp.z) / dfWScale); + qrot.y = (float) ((vRight.z - vForward.x) / dfWScale); + qrot.z = (float) ((vUp.x - vRight.y) / dfWScale); + + return qrot; + } +} diff --git a/util/prioitylist/DefaultPriorityList.java b/util/prioitylist/DefaultPriorityList.java new file mode 100644 index 00000000..87dc68f8 --- /dev/null +++ b/util/prioitylist/DefaultPriorityList.java @@ -0,0 +1,30 @@ +package appeng.util.prioitylist; + +import java.util.ArrayList; +import java.util.List; + +import appeng.api.storage.data.IAEStack; + +public class DefaultPriorityList> implements IPartitionList +{ + + final static List nullList = new ArrayList(); + + public boolean isListed(T input) + { + return false; + } + + @Override + public boolean isEmpty() + { + return true; + } + + @Override + public Iterable getItems() + { + return (Iterable) nullList; + } + +} diff --git a/util/prioitylist/FuzzyPriorityList.java b/util/prioitylist/FuzzyPriorityList.java new file mode 100644 index 00000000..96da3782 --- /dev/null +++ b/util/prioitylist/FuzzyPriorityList.java @@ -0,0 +1,38 @@ +package appeng.util.prioitylist; + +import java.util.Collection; + +import appeng.api.config.FuzzyMode; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +public class FuzzyPriorityList> implements IPartitionList +{ + + final IItemList list; + final FuzzyMode mode; + + public FuzzyPriorityList(IItemList in, FuzzyMode mode) { + list = in; + this.mode = mode; + } + + public boolean isListed(T input) + { + Collection out = list.findFuzzy( input, mode ); + return out != null && !out.isEmpty(); + } + + @Override + public boolean isEmpty() + { + return list.isEmpty(); + } + + @Override + public Iterable getItems() + { + return list; + } + +} diff --git a/util/prioitylist/IPartitionList.java b/util/prioitylist/IPartitionList.java new file mode 100644 index 00000000..d5e5b4c9 --- /dev/null +++ b/util/prioitylist/IPartitionList.java @@ -0,0 +1,14 @@ +package appeng.util.prioitylist; + +import appeng.api.storage.data.IAEStack; + +public interface IPartitionList> +{ + + boolean isListed(T input); + + boolean isEmpty(); + + Iterable getItems(); + +} diff --git a/util/prioitylist/PrecisePriorityList.java b/util/prioitylist/PrecisePriorityList.java new file mode 100644 index 00000000..03086f9d --- /dev/null +++ b/util/prioitylist/PrecisePriorityList.java @@ -0,0 +1,32 @@ +package appeng.util.prioitylist; + +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; + +public class PrecisePriorityList> implements IPartitionList +{ + + final IItemList list; + + public PrecisePriorityList(IItemList in) { + list = in; + } + + public boolean isListed(T input) + { + return list.findPrecise( input ) != null; + } + + @Override + public boolean isEmpty() + { + return list.isEmpty(); + } + + @Override + public Iterable getItems() + { + return list; + } + +}