package zmaster587.advancedRocketry.tile.multiblock; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.TextComponentString; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.ForgeChunkManager.Type; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.entity.EntityItemAbducted; import zmaster587.advancedRocketry.util.AudioRegistry; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.LibVulpesBlocks; import zmaster587.libVulpes.block.BlockMeta; import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.interfaces.ILinkableTile; import zmaster587.libVulpes.inventory.modules.*; import zmaster587.libVulpes.items.ItemLinker; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer; import zmaster587.libVulpes.util.EmbeddedInventory; import zmaster587.libVulpes.util.ZUtils; import zmaster587.libVulpes.util.ZUtils.RedstoneState; import java.util.List; public class TileRailgun extends TileMultiPowerConsumer implements IInventory, ILinkableTile, IGuiCallback { private EmbeddedInventory inv; Ticket ticket; public long recoil; int minStackTransferSize = 1; ModuleNumericTextbox textBox; RedstoneState state; ModuleRedstoneOutputButton redstoneControl; public static final Object[][][] structure = { { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", "coilCopper" , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {null, null, null, null, null}, {null, null, "coilCopper" , null, null}, {null, "coilCopper", Blocks.AIR , "coilCopper", null}, {null, null, "coilCopper" , null, null}, {null, null, null, null, null}}, { {'*', '*', '*', '*', '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', '*', '*', '*', '*'}}, {{'*', '*', 'c', '*', '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', "blockTitanium", "blockTitanium" , "blockTitanium", '*'}, {'*', '*', '*', '*', '*'}} }; public TileRailgun() { inv = new EmbeddedInventory(1); powerPerTick = 100000; redstoneControl = new ModuleRedstoneOutputButton(174, 4, -1, "", this); state = RedstoneState.OFF; redstoneControl.setRedstoneState(state); } @Override protected int requiredPowerPerTick() { BlockPos pos = getDestPosition(); if(pos != null) { int distance = (int)Math.sqrt(Math.pow(pos.getX() - this.pos.getX(),2) + Math.pow(pos.getZ() - this.pos.getZ(), 2)); if(getDestDimId() == this.world.provider.getDimension()) distance = distance*10 + 50000; return Math.min(distance, super.requiredPowerPerTick()); } return super.requiredPowerPerTick(); } /** * @return the destionation DIMID or -1 if not valid */ private int getDestDimId() { ItemStack stack = inv.getStackInSlot(0); if(stack != null && stack.getItem() instanceof ItemLinker) { return ItemLinker.getDimId(stack); } return -1; } /** * @return the destionation DIMID or null if not valid */ private BlockPos getDestPosition() { ItemStack stack = inv.getStackInSlot(0); if(stack != null && stack.getItem() instanceof ItemLinker && ItemLinker.isSet(stack)) { return ItemLinker.getMasterCoords(stack); } return null; } @Override public List<BlockMeta> getAllowableWildCardBlocks() { List<BlockMeta> blocks = super.getAllowableWildCardBlocks(); blocks.addAll(getAllowableBlocks('P')); blocks.addAll(getAllowableBlocks('I')); blocks.addAll(getAllowableBlocks('O')); blocks.add(new BlockMeta(LibVulpesBlocks.blockAdvStructureBlock)); return blocks; } @Override public Object[][][] getStructure() { return structure; } @Override public List<ModuleBase> getModules(int ID, EntityPlayer player) { List<ModuleBase> modules = super.getModules(ID, player); modules.add(new ModuleSlotArray(40, 40, this, 0, 1)); if(world.isRemote) { //if(textBox == null) { textBox = new ModuleNumericTextbox(this, 80, 40, 32, 12, 2); //} textBox.setText(String.valueOf(minStackTransferSize)); modules.add(new ModuleText(60, 25, LibVulpes.proxy.getLocalizedString("msg.railgun.transfermin"), 0x2b2b2b)); modules.add(textBox); } modules.add(redstoneControl); return modules; } @Override public void onLoad() { if(ticket == null) { ticket = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, this.world, Type.NORMAL); if(ticket != null) ForgeChunkManager.forceChunk(ticket, new ChunkPos(getPos().getX() / 16 - (getPos().getX() < 0 ? 1 : 0), getPos().getZ() / 16 - (getPos().getZ() < 0 ? 1 : 0))); } } @Override public void invalidate() { super.invalidate(); ForgeChunkManager.releaseTicket(ticket); } @Override public void onInventoryUpdated() { //Needs completion if(itemInPorts.isEmpty()) { attemptCompleteStructure(world.getBlockState(pos)); } } @Override public void onInventoryButtonPressed(int buttonId) { super.onInventoryButtonPressed(buttonId); if(buttonId == -1) { state = redstoneControl.getState(); PacketHandler.sendToServer(new PacketMachine(this, (byte)5)); } } @Override protected void onRunningPoweredTick() { //Do nothing, or add charge effect } @Override public void useEnergy(int amt) { if(!world.isRemote && enabled && isRedstoneStateSatisfied() && attemptCargoTransfer()) super.useEnergy(amt); } @Override public boolean isRunning() { return isComplete(); } private boolean isRedstoneStateSatisfied() { if(state == RedstoneState.OFF) return true; boolean powered = world.isBlockIndirectlyGettingPowered(pos) > 0; return (state == RedstoneState.ON && powered) || (!powered && state == RedstoneState.INVERTED); } private boolean attemptCargoTransfer() { if(world.isRemote) return false; ItemStack tfrStack = null; IInventory inv2 = null; int index = 0; //BlockPos invPos; out: for(IInventory inv : this.itemInPorts) { for(int i = inv.getSizeInventory() - 1; i >= 0 ; i--) { if((tfrStack = inv.getStackInSlot(i)) != null && inv.getStackInSlot(i).getCount() >= minStackTransferSize) { inv2 = inv; index = i; //invPos = ((TileEntity)inv).getPos(); break out; } else tfrStack = null; } } if(tfrStack != null) { BlockPos pos = getDestPosition(); if(pos != null) { int dimId; dimId = getDestDimId(); if(dimId != -1) { World world = DimensionManager.getWorld(dimId); TileEntity tile; if(world != null && (tile = world.getTileEntity(pos)) instanceof TileRailgun && ((TileRailgun)tile).canRecieveCargo(tfrStack) && zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().areDimensionsInSamePlanetMoonSystem(this.world.provider.getDimension(), zmaster587.advancedRocketry.dimension.DimensionManager.getEffectiveDimId(world, pos).getId())) { ((TileRailgun)tile).onRecieveCargo(tfrStack); inv2.setInventorySlotContents(index, ItemStack.EMPTY); inv2.markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); EnumFacing dir = RotatableBlock.getFront(world.getBlockState(pos)); EntityItemAbducted ent = new EntityItemAbducted(this.world, this.pos.getX() - 2*dir.getFrontOffsetX() + 0.5f, this.pos.getY() + 5, this.pos.getZ() - 2*dir.getFrontOffsetZ() + 0.5f, tfrStack); this.world.spawnEntity(ent); PacketHandler.sendToNearby(new PacketMachine(this, (byte) 3), this.world.provider.getDimension(), this.pos.getX() - dir.getFrontOffsetX(), this.pos.getY() + 5, this.pos.getZ() - dir.getFrontOffsetZ(), 64d); return true; } } } } return false; } public boolean canRecieveCargo(ItemStack stack) { for(IInventory inv : this.itemOutPorts) { if(ZUtils.numEmptySlots(inv) > 0) return true; } return false; } public void onRecieveCargo(ItemStack stack) { for(IInventory inv : this.itemOutPorts) { if(ZUtils.doesInvHaveRoom(stack, inv)) { ZUtils.mergeInventory(stack, inv); break; } } } @Override public String getMachineName() { return "tile.railgun.name"; } @Override public AxisAlignedBB getRenderBoundingBox() { return new AxisAlignedBB(this.pos.getX() -5, this.pos.getY(), this.pos.getZ() - 5, this.pos.getX() + 5, this.pos.getY() +10, this.pos.getZ() + 5); } @Override public int getSizeInventory() { return 1; } @Override public ItemStack getStackInSlot(int i) { return inv.getStackInSlot(i); } @Override public ItemStack decrStackSize(int i, int j) { return inv.decrStackSize(i, j); } @Override public void setInventorySlotContents(int i, ItemStack j) { inv.setInventorySlotContents(i, j); } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUsableByPlayer(EntityPlayer player) { return true; } @Override public boolean isEmpty() { return inv.isEmpty(); } @Override public void openInventory(EntityPlayer player) { } @Override public void closeInventory(EntityPlayer player) { } @Override public boolean isItemValidForSlot(int i, ItemStack stack) { return stack == null || stack.getItem() instanceof ItemLinker; } @Override public boolean onLinkStart(ItemStack item, TileEntity entity, EntityPlayer player, World world) { ItemLinker.setMasterCoords(item, this.getPos()); ItemLinker.setDimId(item, world.provider.getDimension()); if(!world.isRemote) player.sendMessage(new TextComponentString(LibVulpes.proxy.getLocalizedString("msg.linker.program"))); return true; } @Override public boolean onLinkComplete(ItemStack item, TileEntity entity, EntityPlayer player, World world) { return false; } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); inv.writeToNBT(nbt); nbt.setInteger("minTfrSize", minStackTransferSize); nbt.setByte("redstoneState", (byte) state.ordinal()); return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); inv.readFromNBT(nbt); minStackTransferSize = nbt.getInteger("minTfrSize"); state = RedstoneState.values()[nbt.getByte("redstoneState")]; redstoneControl.setRedstoneState(state); } @Override public void writeDataToNetwork(ByteBuf out, byte id) { if(id == 4) out.writeInt(minStackTransferSize); else if(id == 5) out.writeByte(state.ordinal()); else super.writeDataToNetwork(out, id); } @Override public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { if(packetId == 4) nbt.setInteger("minTransferSize", in.readInt()); else if(packetId == 5) nbt.setByte("state", in.readByte()); else super.readDataFromNetwork(in, packetId, nbt); } @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if(side.isClient()) { if(id == 3) { EnumFacing dir = RotatableBlock.getFront(world.getBlockState(pos)); LibVulpes.proxy.playSound(world, pos, AudioRegistry.railgunFire, SoundCategory.BLOCKS, Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.BLOCKS), 0.975f + world.rand.nextFloat()*0.05f); recoil = world.getTotalWorldTime(); } } else if(id == 4) { minStackTransferSize = nbt.getInteger("minTransferSize"); } else if(id == 5) { state = RedstoneState.values()[nbt.getByte("state")]; } else super.useNetworkData(player, side, id, nbt); } @Override public void onModuleUpdated(ModuleBase module) { if(module == textBox) { if(textBox.getText().isEmpty()) minStackTransferSize = 1; else minStackTransferSize = MathHelper.clamp(Integer.parseInt(textBox.getText()),1, 64); PacketHandler.sendToServer(new PacketMachine(this, (byte)4)); } } @Override protected void writeNetworkData(NBTTagCompound nbt) { super.writeNetworkData(nbt); nbt.setByte("state", (byte)state.ordinal()); nbt.setInteger("minTfrSize", minStackTransferSize); } @Override protected void readNetworkData(NBTTagCompound nbt) { super.readNetworkData(nbt); state = RedstoneState.values()[nbt.getByte("redstoneState")]; redstoneControl.setRedstoneState(state); minStackTransferSize = nbt.getInteger("minTfrSize"); } @Override public String getName() { return getMachineName(); } @Override public boolean hasCustomName() { return false; } @Override public ItemStack removeStackFromSlot(int index) { return inv.removeStackFromSlot(index); } @Override public int getField(int id) { return inv.getField(id); } @Override public void setField(int id, int value) { inv.setField(id, value); } @Override public int getFieldCount() { return inv.getFieldCount(); } @Override public void clear() { inv.clear(); } }