package info.jbcs.minecraft.vending.block; import com.kamildanak.minecraft.enderpay.api.EnderPayApi; import com.kamildanak.minecraft.enderpay.api.NoSuchAccountException; import com.kamildanak.minecraft.enderpay.api.NotABanknoteException; import info.jbcs.minecraft.vending.Utils; import info.jbcs.minecraft.vending.Vending; import info.jbcs.minecraft.vending.tileentity.TileEntityVendingMachine; import net.minecraft.block.BlockContainer; import net.minecraft.block.BlockDoor; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Optional; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; import java.util.Objects; import static info.jbcs.minecraft.vending.General.countNotNull; public class BlockVendingMachine extends BlockContainer { private static final PropertyEnum<EnumSupports> SUPPORT = PropertyEnum.create("support", EnumSupports.class); private boolean isAdvanced, isMultiple, isOpen; private String name; public BlockVendingMachine(boolean advanced, boolean multiple, String name) { super(Material.GLASS); setProperties(); register(name); isAdvanced = advanced; isMultiple = multiple; isOpen = true; } private static boolean checkIfFits(@Nonnull ItemStack bought, @Nonnull ItemStack offered, NonNullList<ItemStack> soldItems, TileEntityVendingMachine tileEntity) { if (Loader.isModLoaded("enderpay")) { if (bought.isEmpty() && tileEntity.soldCreditsSum() > 0) return true; if (Utils.isBanknote(bought) && tileEntity.boughtCreditsSum() == 0) return countNotNull(soldItems) > 0; if (Utils.isFilledBanknote(bought)) return (tileEntity.boughtCreditsSum() > 0 && tileEntity.hasPlaceForBanknote()); } if (bought.isEmpty()) return countNotNull(soldItems)>0; return tileEntity.doesStackFit(bought) && !offered.isEmpty() && bought.getItem() == offered.getItem() && bought.getItemDamage() == offered.getItemDamage() && offered.getCount() >= bought.getCount() && Objects.equals(bought.getTagCompound(), offered.getTagCompound()); } @Optional.Method(modid = "enderpay") private static void takeCredits(EntityPlayer entityplayer, TileEntityVendingMachine tileEntity, @Nonnull ItemStack bought) { try { long amount = EnderPayApi.getBanknoteOriginalValue(bought); EnderPayApi.addToBalance(entityplayer.getUniqueID(), -amount); if (tileEntity.isInfinite()) return; for (int i = 0; i < 9; i++) { ItemStack itemStack = tileEntity.inventory.getStackInSlot(i); if (itemStack.isEmpty()) { tileEntity.inventory.setInventorySlotContents(i, EnderPayApi.getBanknote(amount)); break; } if (Utils.isBanknote(itemStack)) { tileEntity.inventory.setInventorySlotContents(i, EnderPayApi.getBanknote(amount + EnderPayApi.getBanknoteCurrentValue(itemStack))); break; } } } catch (NoSuchAccountException | NotABanknoteException ignored) { } } @Optional.Method(modid = "enderpay") private static void giveCredits(EntityPlayer entityplayer, TileEntityVendingMachine tileEntity) { try { long soldAmount = tileEntity.soldCreditsSum(); EnderPayApi.addToBalance(entityplayer.getUniqueID(), soldAmount); if (tileEntity.isInfinite()) return; long inventorySum = tileEntity.realInventoryCreditsSum(); long totalSum = tileEntity.realTotalCreditsSum(); for (int i = 0; i < 9; i++) { if (Utils.isBanknote(tileEntity.inventory.getStackInSlot(i))) { tileEntity.inventory.setInventorySlotContents(i, ItemStack.EMPTY); } } if (inventorySum >= soldAmount) { for (int i = 0; i < 9; i++) { if (tileEntity.inventory.getStackInSlot(i).isEmpty()) { tileEntity.inventory.setInventorySlotContents(i, inventorySum - soldAmount > 0 ? EnderPayApi.getBanknote(inventorySum - soldAmount) : ItemStack.EMPTY); break; } } } else { if (tileEntity.isMultiple()) { for (int i = 9; i < 13; i++) { if (Utils.isBanknote(tileEntity.inventory.getStackInSlot(i))) { tileEntity.inventory.setInventorySlotContents(i, ItemStack.EMPTY); } } for (int i = 9; i < 13; i++) { if (tileEntity.inventory.getStackInSlot(i).isEmpty()) { tileEntity.inventory.setInventorySlotContents(i, EnderPayApi.getBanknote(totalSum - soldAmount)); break; } } } else { tileEntity.inventory.setInventorySlotContents(9, totalSum - soldAmount > 0 ? EnderPayApi.getBanknote(totalSum - soldAmount) : ItemStack.EMPTY); } } } catch (NoSuchAccountException e) { e.printStackTrace(); } } @Optional.Method(modid = "enderpay") private static boolean checkIfPlayerHasEnoughtCredits(EntityPlayer entityPlayer, TileEntityVendingMachine tileEntity, @Nonnull ItemStack bought) { if (Loader.isModLoaded("enderpay")) { if (!Utils.isBanknote(bought)) return true; try { return EnderPayApi.getBalance(entityPlayer.getUniqueID()) >= tileEntity.boughtCreditsSum(); } catch (NoSuchAccountException ignored) { return false; } } return true; } private void setProperties() { setSoundType(SoundType.GLASS); setHardness(0.3F); setResistance(6000000.0F); setBlockUnbreakable(); setCreativeTab(Vending.tabVending); } private void register(String name) { this.name = name; setUnlocalizedName(name); setRegistryName(name); this.setDefaultState(this.blockState.getBaseState().withProperty(SUPPORT, EnumSupports.STONE)); GameRegistry.register(this); GameRegistry.register(new ItemBlock(this).setRegistryName(name).setHasSubtypes(true).setMaxDamage(0)); } private void vend(World world, BlockPos blockPos, EntityPlayer entityplayer) { TileEntityVendingMachine tileEntity = (TileEntityVendingMachine) world.getTileEntity(blockPos); if (tileEntity == null) return; if (!tileEntity.isOpen()) { world.playSound(entityplayer, blockPos, Vending.sound_forbidden, SoundCategory.MASTER, 0.3f, 0.6f); return; } NonNullList<ItemStack> soldItems = tileEntity.getSoldItems(); ItemStack bought = tileEntity.getBoughtItems().get(0); ItemStack offered = entityplayer.inventory.getCurrentItem(); boolean playerHasEnoughtCredits = true; boolean machineHasEnoughtCredits = true; if (Loader.isModLoaded("enderpay")) { for (int i = 0; i < soldItems.size(); i++) { if (Utils.isBanknote(soldItems.get(i))) soldItems.set(i,ItemStack.EMPTY); } playerHasEnoughtCredits = checkIfPlayerHasEnoughtCredits(entityplayer, tileEntity, bought); machineHasEnoughtCredits = checkIfMachineHasEnoughtCredits(tileEntity); } boolean fits = checkIfFits(bought, offered, soldItems, tileEntity) && playerHasEnoughtCredits && machineHasEnoughtCredits; if (fits && !world.isRemote) { giveItems(soldItems, entityplayer, world, blockPos, tileEntity); boolean takeItems = true; if (Loader.isModLoaded("enderpay")) { if (tileEntity.soldCreditsSum() > 0) giveCredits(entityplayer, tileEntity); if (tileEntity.boughtCreditsSum() > 0) takeCredits(entityplayer, tileEntity, bought); if (tileEntity.getBoughtItems().size() > 0 && Utils.isBanknote(tileEntity.getBoughtItems().get(0))) takeItems = false; } if(takeItems) takeItems(entityplayer, tileEntity, bought, offered); if (!tileEntity.isInfinite()) tileEntity.inventory.onInventoryChanged(); } world.playSound(entityplayer, blockPos, fits ? Vending.sound_processed : Vending.sound_forbidden, SoundCategory.MASTER, 0.3f, 0.6f); } private boolean checkIfMachineHasEnoughtCredits(TileEntityVendingMachine tileEntity) { if (tileEntity.isInfinite() || !Loader.isModLoaded("enderpay")) return true; long soldSum = tileEntity.soldCreditsSum(); long realTotalSum = tileEntity.realTotalCreditsSum(); return soldSum <= realTotalSum; } private void takeItems(EntityPlayer entityplayer, TileEntityVendingMachine tileEntity, @Nonnull ItemStack bought, @Nonnull ItemStack offered) { if (!offered.isEmpty()) { ItemStack paid = offered.splitStack(bought.getCount()); if (offered.getCount() == 0) { entityplayer.inventory.setInventorySlotContents(entityplayer.inventory.currentItem,ItemStack.EMPTY); } if (!tileEntity.isInfinite()) tileEntity.inventory.addItemStackToInventory(paid, 0, 8); } } private void giveItems(NonNullList<ItemStack> soldItems, EntityPlayer entityPlayer, World world, BlockPos blockPos, TileEntityVendingMachine tileEntity) { if (countNotNull(soldItems) == 0) return; NonNullList<ItemStack> soldItemsOld = NonNullList.withSize(soldItems.size(), ItemStack.EMPTY); if (Vending.close_on_partial_sold_out) for (int i = 0; i < soldItems.size(); i++) if (!soldItems.get(i).isEmpty()) soldItemsOld.set(i,soldItems.get(i).copy()); for (ItemStack sold : soldItems) { if (sold.isEmpty()) continue; NBTTagCompound tag = new NBTTagCompound(); sold.writeToNBT(tag); ItemStack vended = new ItemStack(tag); if (!tileEntity.isInfinite()) { tileEntity.inventory.takeItems(sold, sold.getItemDamage(), sold.getCount()); } boolean spawnItem = true; if (Vending.transfer_to_inventory) spawnItem = !entityPlayer.inventory.addItemStackToInventory(vended); if (spawnItem) Utils.throwItemAtPlayer(entityPlayer, world, blockPos, vended); } if (Vending.close_on_sold_out && countNotNull(tileEntity.getSoldItems()) == 0) tileEntity.setOpen(false); if (Vending.close_on_partial_sold_out) closeIfSoldChanged(tileEntity, soldItems, soldItemsOld); } private void closeIfSoldChanged(TileEntityVendingMachine tileEntity, NonNullList<ItemStack> soldItems, NonNullList<ItemStack> soldItemsOld) { for (int i = 0; i < soldItemsOld.size(); i++) { //System.out.println(!soldItemsOld.get(i).isEmpty() ? soldItemsOld.get(i).toString() : "null"); //System.out.println(!tileEntity.getSoldItems().get(i).isEmpty() ? soldItemsOld.get(i).toString() : "null"); if (soldItemsOld.get(i).isEmpty() && tileEntity.getSoldItems().get(i).isEmpty()) continue; if (soldItemsOld.get(i).isEmpty() || tileEntity.getSoldItems().get(i).isEmpty()) tileEntity.setOpen(false); if (soldItemsOld.get(i).getCount() != soldItems.get(i).getCount()) tileEntity.setOpen(false); } } @Override public void onBlockClicked(World world, BlockPos blockPos, EntityPlayer entityplayer) { TileEntityVendingMachine tileEntity = (TileEntityVendingMachine) world.getTileEntity(blockPos); if (tileEntity == null) return; if (!entityplayer.getDisplayNameString().equals(tileEntity.getOwnerName()) || !tileEntity.inventory.isEmpty()) { vend(world, blockPos, entityplayer); return; } dropBlockAsItem(world, blockPos, world.getBlockState(blockPos), 0); world.setBlockToAir(blockPos); world.playSound(entityplayer, blockPos, Vending.sound_processed, SoundCategory.MASTER, 0.3f, 0.6f); } @Override public boolean onBlockActivated(World world, BlockPos blockPos, IBlockState state, EntityPlayer entityPlayer, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { TileEntityVendingMachine tileEntity = (TileEntityVendingMachine) world.getTileEntity(blockPos); if (tileEntity == null) return false; if (!entityPlayer.inventory.getCurrentItem().isEmpty() && entityPlayer.inventory.getCurrentItem().getItem() == Vending.itemWrench) { Vending.guiWrench.open(entityPlayer, world, blockPos); return true; } if (entityPlayer.getDisplayNameString().equals(tileEntity.getOwnerName()) && !entityPlayer.isSneaking()) { Vending.guiVending.open(entityPlayer, world, blockPos); return true; } if (entityPlayer.capabilities.isCreativeMode && !entityPlayer.isSneaking()) { Vending.guiVending.open(entityPlayer, world, blockPos); return true; } vend(world, blockPos, entityPlayer); tileEntity.markDirty(); tileEntity.markBlockForUpdate(blockPos); return true; } @Override public boolean canPlaceBlockAt(World worldIn, @Nonnull BlockPos pos) { if (!worldIn.getBlockState(pos).getBlock().isReplaceable(worldIn, pos)) return false; if (!Vending.block_placing_next_to_doors) return true; for (int x = -1; x < 2; x++) for (int z = -1; z < 2; z++) if (worldIn.getBlockState(pos.add(x, 0, z)).getBlock() instanceof BlockDoor) return false; return true; } @Override public void onBlockPlacedBy(World world, BlockPos blockPos, IBlockState state, EntityLivingBase entityLiving, @Nonnull ItemStack stack) { world.setBlockState(blockPos, getStateFromMeta(stack.getMetadata())); TileEntityVendingMachine e = new TileEntityVendingMachine(isAdvanced, false, isMultiple); e.setOpen(isOpen); if (entityLiving != null) { EntityPlayer player = (EntityPlayer) entityLiving; e.setOwnerName(player.getDisplayNameString()); world.setTileEntity(blockPos, e); } } @Override @Nonnull public TileEntity createNewTileEntity(@Nonnull World var1, int metadata) { TileEntityVendingMachine e = new TileEntityVendingMachine(isAdvanced, false, isMultiple); e.setOpen(isOpen); return e; } @Override public void breakBlock(World world, @Nonnull BlockPos blockPos, @Nonnull IBlockState state) { TileEntityVendingMachine tileEntityChest = (TileEntityVendingMachine) world.getTileEntity(blockPos); if (tileEntityChest == null) return; for (int l = 0; l < tileEntityChest.getSizeInventory(); l++) { ItemStack itemstack = tileEntityChest.getStackInSlot(l); if (itemstack.isEmpty()) continue; if (l == 10 && tileEntityChest.isAdvanced()) continue; float f = world.rand.nextFloat() * 0.8F + 0.1F; float f1 = world.rand.nextFloat() * 0.8F + 0.1F; float f2 = world.rand.nextFloat() * 0.8F + 0.1F; while (itemstack.getCount() > 0) { int i1 = world.rand.nextInt(21) + 10; if (i1 > itemstack.getCount()) { i1 = itemstack.getCount(); } itemstack.setCount(itemstack.getCount()-i1); NBTTagCompound tag = new NBTTagCompound(); itemstack.writeToNBT(tag); ItemStack toSpawn = new ItemStack(tag); toSpawn.setCount(i1); EntityItem entityitem = new EntityItem(world, blockPos.getX() + f, blockPos.getY() + f1, blockPos.getZ() + f2, toSpawn); float f3 = 0.05F; entityitem.motionX = (float) world.rand.nextGaussian() * f3; entityitem.motionY = (float) world.rand.nextGaussian() * f3 + 0.2F; entityitem.motionZ = (float) world.rand.nextGaussian() * f3; world.spawnEntity(entityitem); } } super.breakBlock(world, blockPos, state); } @SuppressWarnings("deprecation") @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public int damageDropped(IBlockState state) { return getMetaFromState(state); } @Override @SideOnly(Side.CLIENT) public void getSubBlocks(@Nonnull Item item, CreativeTabs tab, NonNullList<ItemStack> list) { for (int i = 0; i < EnumSupports.length; ++i) list.add(new ItemStack(item, 1, i)); } @SuppressWarnings("deprecation") @Override @Nonnull public IBlockState getStateFromMeta(int meta) { return this.getDefaultState().withProperty(SUPPORT, EnumSupports.byMetadata(meta)); } @Override public int getMetaFromState(IBlockState state) { return state.getValue(SUPPORT).getMetadata(); } @Override @Nonnull protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, SUPPORT); } @Override @SuppressWarnings("deprecation") @Nonnull public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return new AxisAlignedBB(0.0625f, 0.125f, 0.0625f, 0.9375f, 0.9375f, 0.9375f); } @Override @Nonnull public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.MODEL; } @Override @SuppressWarnings("deprecation") public boolean isFullCube(IBlockState state) { return false; } @Override @Nonnull public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT; } public String getName() { return name; } @Override @Nonnull public String getLocalizedName() { return net.minecraft.client.resources.I18n.format("tile." + getName() + ".name").trim(); } }