BlockAllocator.java (14674B)
1 package ambos.simpletech.block; 2 3 import net.minecraft.core.block.Block; 4 import net.minecraft.core.block.BlockTileEntity; 5 import net.minecraft.core.block.entity.TileEntity; 6 import net.minecraft.core.block.entity.TileEntityChest; 7 import net.minecraft.core.block.entity.TileEntityFurnace; 8 import net.minecraft.core.block.material.Material; 9 import net.minecraft.core.entity.Entity; 10 import net.minecraft.core.entity.EntityItem; 11 import net.minecraft.core.entity.EntityLiving; 12 import net.minecraft.core.entity.player.EntityPlayer; 13 import net.minecraft.core.entity.vehicle.EntityMinecart; 14 import net.minecraft.core.item.ItemStack; 15 import net.minecraft.core.player.inventory.IInventory; 16 import net.minecraft.core.player.inventory.InventoryLargeChest; 17 import net.minecraft.core.sound.SoundType; 18 import net.minecraft.core.util.helper.Direction; 19 import net.minecraft.core.util.helper.Side; 20 import net.minecraft.core.util.phys.AABB; 21 import net.minecraft.core.world.World; 22 23 import java.util.List; 24 import java.util.Random; 25 26 import ambos.simpletech.IPlayerDisplayer; 27 import ambos.simpletech.SimpleTech; 28 import ambos.simpletech.block.entity.TileEntityAllocator; 29 30 public class BlockAllocator extends BlockTileEntity { 31 private final boolean allowFiltering; 32 private final boolean subItemFiltering; 33 34 public BlockAllocator(String key, int id, Material material, boolean allowFiltering, boolean subItemFiltering) { 35 super(key, id, material); 36 this.allowFiltering = allowFiltering; 37 this.subItemFiltering = subItemFiltering; 38 } 39 40 @Override 41 protected TileEntity getNewBlockEntity() { 42 return new TileEntityAllocator(); 43 } 44 45 @Override 46 public boolean blockActivated(World world, int x, int y, int z, EntityPlayer player) { 47 if (!this.allowFiltering) { 48 return false; 49 } else if (world.isClientSide) { 50 return true; 51 } else { 52 TileEntityAllocator allocator = (TileEntityAllocator) world.getBlockTileEntity(x, y, z); 53 ((IPlayerDisplayer) player).simple_tech$displayGUIAllocator(allocator); 54 return true; 55 } 56 } 57 58 @Override 59 public void updateTick(World world, int x, int y, int z, Random rand) { 60 if (world.isBlockIndirectlyGettingPowered(x, y, z) || world.isBlockIndirectlyGettingPowered(x, y + 1, z)) { 61 this.allocateItems(world, x, y, z, rand); 62 } 63 } 64 65 @Override 66 public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) { 67 if (blockId > 0 && Block.blocksList[blockId].canProvidePower() && 68 (world.isBlockIndirectlyGettingPowered(x, y, z) || 69 world.isBlockIndirectlyGettingPowered(x, y + 1, z))) { 70 world.scheduleBlockUpdate(x, y, z, this.id, this.tickRate()); 71 } 72 } 73 74 @Override 75 public int tickRate() { 76 return 1; 77 } 78 79 @Override 80 public void onBlockAdded(World world, int x, int y, int z) { 81 super.onBlockAdded(world, x, y, z); 82 } 83 84 @Override 85 public int getBlockTextureFromSideAndMetadata(Side side, int meta) { 86 int direction = SimpleTech.get3DDirectionFromMeta(meta); 87 88 if (direction > 5) { 89 return this.atlasIndices[Side.WEST.getId()]; // Defaults to top/bottom texture. 90 } else if (side.getId() == SimpleTech.getOppositeDirectionById(direction)) { 91 if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { 92 return this.atlasIndices[Side.TOP.getId()]; // Returns back top/bottom texture. 93 } 94 return this.atlasIndices[Side.NORTH.getId()]; // Returns back texture. 95 } else if (side.getId() == direction) { 96 if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { 97 return this.atlasIndices[Side.BOTTOM.getId()]; // Returns front top/bottom texture. 98 } 99 return this.atlasIndices[Side.SOUTH.getId()]; // Returns front texture. 100 } else { 101 if (side.getId() == Side.TOP.getId() || side.getId() == Side.BOTTOM.getId()) { 102 return this.atlasIndices[Side.WEST.getId()]; // Returns top/bottom texture. 103 } else { 104 return this.atlasIndices[Side.EAST.getId()]; // Returns side texture. 105 } 106 } 107 } 108 109 @Override 110 public void onBlockPlaced(World world, int x, int y, int z, Side side, EntityLiving entity, double sideHeight) { 111 Direction placementDirection = entity.getPlacementDirection(side).getOpposite(); 112 world.setBlockMetadataWithNotify(x, y, z, placementDirection.getId()); 113 } 114 115 public int getRandomItemFromContainer(IInventory inventory, Random rand, World world, int x, int y, int z) { 116 if (inventory == null) { 117 return -1; 118 } else { 119 int i = -1; 120 int j = 1; 121 122 byte startAt = 0; 123 124 if (inventory instanceof TileEntityFurnace) { 125 startAt = 2; 126 } 127 128 for (int k = startAt; k < inventory.getSizeInventory(); ++k) { 129 if (inventory.getStackInSlot(k) != null && this.passesFilter(world, x, y, z, 130 inventory.getStackInSlot(k)) && rand.nextInt(j) == 0) { 131 i = k; 132 ++j; 133 } 134 } 135 136 return i; 137 } 138 } 139 140 protected IInventory containerAtPos(World world, int x, int y, int z) { 141 TileEntity tile = world.getBlockTileEntity(x, y, z); 142 return !(tile instanceof IInventory) ? null : this.getDoubleChest(world, x, y, z); 143 } 144 145 protected boolean blockingCubeAtPos(World world, int x, int y, int z) { 146 int blockID = world.getBlockId(x, y, z); 147 boolean isOpaque = Block.translucent[blockID]; 148 149 return isOpaque || blockID == Block.glass.id || 150 blockID == Block.cactus.id || 151 blockID == Block.cake.id || 152 blockID == Block.blockSnow.id || 153 blockID == Block.mobspawner.id || 154 blockID == Block.fencePlanksOak.id; 155 } 156 157 private void putItemInContainer(IInventory inventory, ItemStack item, int index) { 158 if (item != null) { 159 if (index >= 0) { 160 ItemStack stack = inventory.getStackInSlot(index); 161 162 if (stack != null) { 163 stack.stackSize += item.stackSize; 164 inventory.setInventorySlotContents(index, stack); 165 } else { 166 inventory.setInventorySlotContents(index, item); 167 } 168 } 169 } 170 } 171 172 private void dispenseItem(World world, int x, int y, int z, int dx, int dy, int dz, ItemStack item, Random rand) { 173 double d = (double) x + (double) dx * 0.5D + 0.5D; 174 double d1 = (double) y + (double) dy * 0.5D + 0.5D; 175 double d2 = (double) z + (double) dz * 0.5D + 0.5D; 176 double d3 = rand.nextDouble() * 0.1D + 0.2D; 177 178 EntityItem entityItem = new EntityItem(world, d, d1, d2, item); 179 180 // Item movement. 181 entityItem.xd = (double) dx * d3; 182 entityItem.yd = (double) dy * d3; 183 entityItem.zd = (double) dz * d3; 184 entityItem.xd += rand.nextGaussian() * (double) 0.0075F * 6.0D; 185 entityItem.yd += rand.nextGaussian() * (double) 0.0075F * 6.0D; 186 entityItem.xd += rand.nextGaussian() * (double) 0.0075F * 6.0D; 187 188 world.entityJoinedWorld(entityItem); 189 world.playSoundEffect(SoundType.GUI_SOUNDS, x, y, z, "random.click", 1.0f, 1.0f); 190 191 // Particle rendering. 192 for (int i = 0; i < 10; ++i) { 193 double d4 = rand.nextDouble() * 0.2D + 0.01D; 194 double d5 = d + (double) dx * 0.01D + (rand.nextDouble() - 0.5D) * (double) dz * 0.5D; 195 double d6 = d1 + (rand.nextDouble() - 0.5D) * 0.5D; 196 double d7 = d2 + (double) dz * 0.01D + (rand.nextDouble() - 0.5D) * (double) dx * 0.5D; 197 double d8 = (double) dx * d4 + rand.nextGaussian() * 0.01D; 198 double d9 = -0.03D + rand.nextGaussian() * 0.01D; 199 double d10 = (double) dz * d4 + rand.nextGaussian() * 0.01D; 200 201 world.spawnParticle("smoke", d5, d6, d7, d8, d9, d10); 202 } 203 } 204 205 private boolean outputItem(World world, int x, int y, int z, int dx, int dy, int dz, ItemStack item, Random rand) { 206 IInventory outputContainer = this.containerAtPos(world, x + dx, y + dy, z + dz); 207 208 if (outputContainer == null) { 209 List<Entity> index = world.getEntitiesWithinAABB(IInventory.class, AABB.getBoundingBoxFromPool( 210 x + dx, y + dy, z + dz, x + dx + 1, y + dy + 1, z + dz + 1)); 211 212 if (!index.isEmpty() && (!(index.get(0) instanceof EntityMinecart) || 213 ((EntityMinecart) index.get(0)).minecartType == 1)) { 214 outputContainer = (IInventory) index.get(0); 215 } 216 } 217 218 if (outputContainer == null) { 219 if (!this.blockingCubeAtPos(world, x + dx, y + dy, z + dz)) { 220 this.dispenseItem(world, x, y, z, dx, dy, dz, item, rand); 221 222 return true; 223 } 224 } else { 225 int index1 = this.getFirstFreeInventorySlotOfKind(outputContainer, item); 226 227 if (index1 >= 0) { 228 this.putItemInContainer(outputContainer, item, index1); 229 return true; 230 } 231 } 232 233 return false; 234 } 235 236 private IInventory getDoubleChest(World world, int x, int y, int z) { 237 TileEntity tileEntity = world.getBlockTileEntity(x, y, z); 238 if (!(tileEntity instanceof TileEntityChest)) { 239 return tileEntity instanceof IInventory ? (IInventory) tileEntity : null; 240 } else { 241 int blockId = world.getBlockId(x, y, z); 242 243 IInventory chest1 = (IInventory) world.getBlockTileEntity(x, y, z); 244 IInventory chest2; 245 246 if (world.getBlockId(x + 1, y, z) == blockId) { 247 chest2 = (IInventory) world.getBlockTileEntity(x + 1, y, z); 248 249 return new InventoryLargeChest("", chest1, chest2); 250 } else if (world.getBlockId(x - 1, y, z) == blockId) { 251 chest2 = (IInventory) world.getBlockTileEntity(x - 1, y, z); 252 253 return new InventoryLargeChest("", chest2, chest1); 254 } else if (world.getBlockId(x, y, z + 1) == blockId) { 255 chest2 = (IInventory) world.getBlockTileEntity(x, y, z + 1); 256 257 return new InventoryLargeChest("", chest1, chest2); 258 } else if (world.getBlockId(x, y, z - 1) == blockId) { 259 chest2 = (IInventory) world.getBlockTileEntity(x, y, z - 1); 260 261 return new InventoryLargeChest("", chest2, chest1); 262 } else { 263 return chest1; 264 } 265 } 266 } 267 268 private void allocateItems(World world, int x, int y, int z, Random rand) { 269 int dx = SimpleTech.getDirectionX(world, x, y, z); 270 int dy = SimpleTech.getDirectionY(world, x, y, z); 271 int dz = SimpleTech.getDirectionZ(world, x, y, z); 272 273 IInventory inputContainer = this.containerAtPos(world, x - dx, y - dy, z - dz); 274 275 List<Entity> entities; 276 277 if (inputContainer == null) { 278 entities = world.getEntitiesWithinAABB(IInventory.class, AABB.getBoundingBoxFromPool( 279 x - dx, y - dy, z - dz, x - dx + 1, y - dy + 1, z - dz + 1)); 280 281 if (!entities.isEmpty() && (!(entities.get(0) instanceof EntityMinecart) || 282 ((EntityMinecart) entities.get(0)).minecartType == 1)) { 283 inputContainer = (IInventory) entities.get(0); 284 } 285 } 286 287 int itemIndex; 288 if (inputContainer == null) { 289 entities = world.getEntitiesWithinAABB(EntityItem.class, AABB.getBoundingBoxFromPool( 290 x - dx, y - dy, z - dz, x - dx + 1, y - dy + 1, z - dz + 1)); 291 292 for (itemIndex = 0; itemIndex < entities.size(); ++itemIndex) { 293 if (entities.get(itemIndex) instanceof EntityItem) { 294 EntityItem itemType = (EntityItem) entities.get(itemIndex); 295 296 if (itemType.isAlive() && this.passesFilter(world, x, y, z, itemType.item) && 297 this.outputItem(world, x, y, z, dx, dy, dz, itemType.item, rand)) { 298 itemType.outOfWorld(); 299 } 300 } 301 } 302 } else { 303 itemIndex = this.getRandomItemFromContainer(inputContainer, rand, world, x, y, z); 304 305 if (itemIndex >= 0) { 306 int itemDamage = inputContainer.getStackInSlot(itemIndex).getItemDamageForDisplay(); 307 308 ItemStack item = new ItemStack(inputContainer.getStackInSlot(itemIndex) 309 .getItem(), 1, itemDamage); 310 311 if (this.outputItem(world, x, y, z, dx, dy, dz, item, rand)) { 312 inputContainer.decrStackSize(itemIndex, 1); 313 } 314 } 315 } 316 } 317 318 private int getFirstFreeInventorySlotOfKind(IInventory inventory, ItemStack item) { 319 int inventorySize = inventory.getSizeInventory(); 320 321 if (inventory instanceof TileEntityFurnace) { 322 --inventorySize; 323 } 324 325 for (int i = 0; i < inventorySize; ++i) { 326 boolean canStack = false; 327 328 if (inventory.getStackInSlot(i) != null && inventory.getStackInSlot(i).itemID == item.itemID && 329 (!item.getItem().getHasSubtypes() || 330 inventory.getStackInSlot(i).getItemDamageForDisplay() == item.getItemDamageForDisplay())) { 331 canStack = inventory.getStackInSlot(i).stackSize <= item.getMaxStackSize() - item.stackSize; 332 } 333 334 if (inventory.getStackInSlot(i) == null || canStack) { 335 return i; 336 } 337 } 338 339 return -1; 340 } 341 342 private boolean passesFilter(World world, int x, int y, int z, ItemStack item) { 343 if (!this.allowFiltering) { 344 return true; 345 } else { 346 TileEntityAllocator tileentityallocator = (TileEntityAllocator) world.getBlockTileEntity(x, y, z); 347 ItemStack filterItem = tileentityallocator.getStackInSlot(0); 348 if (filterItem == null) { 349 return true; 350 } else { 351 boolean filterSubItems = true; 352 if (this.subItemFiltering) { 353 filterSubItems = filterItem.getItemDamageForDisplay() == item.getItemDamageForDisplay(); 354 } 355 356 return filterItem.itemID == item.getItem().id && filterSubItems; 357 } 358 } 359 } 360 }