package de.impelon.disenchanter.inventory;

import de.impelon.disenchanter.DisenchantingUtils;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class ContainerDisenchantmentManual extends ContainerDisenchantmentBase {

	protected boolean outputUpdatesDisabeled;
	/**
	 * Must <b>NOT</b> be initialized here, as that would override whatever was
	 * initialized during the calling of the super-constructor.
	 */
	protected AbstractDisenchantmentItemStackHandler tableContent;

	public ContainerDisenchantmentManual(InventoryPlayer playerInventory, World world, BlockPos position) {
		super(playerInventory, world, position);
		this.outputUpdatesDisabeled = false;
	}

	@Override
	protected AbstractDisenchantmentItemStackHandler getTableInventory() {
		if (this.tableContent == null) {
			this.tableContent = new DisenchantmentItemStackHandler() {
				@Override
				protected void onContentsChanged(int slot) {
					super.onContentsChanged(slot);
					ContainerDisenchantmentManual.this.onTableContentChanged(slot);
				};
			};
		}
		return this.tableContent;
	}

	@Override
	public void onContainerClosed(EntityPlayer p) {
		super.onContainerClosed(p);

		if (!this.world.isRemote)
			InventoryUtils.returnInventoryToPlayer(p, p.world, this.getTableInventory());
	}

	protected void onTableContentChanged(int slot) {
		this.updateOutput();
		this.detectAndSendChanges();
	}

	public void updateOutput() {
		if (!this.world.isRemote && !this.outputUpdatesDisabeled) {
			ItemStack source = this.getTableInventory().getSourceStack();
			ItemStack receiver = this.getTableInventory().getReceiverStack();
			ItemStack target = DisenchantingUtils.getAppropriateResultTarget(receiver);
			if (!source.isEmpty() && !target.isEmpty() && DisenchantingUtils.disenchant(source.copy(), target, false,
					true, this.world, this.position, this.random)) {
				if (!(ItemStack.areItemStacksEqual(this.getTableInventory().getOutputStack(), target)))
					this.getTableInventory().setOutputStack(target);
			} else if (!this.getTableInventory().getOutputStack().isEmpty())
				this.getTableInventory().setOutputStack(ItemStack.EMPTY);
		}
	}

	@Override
	public ItemStack slotClick(int slot, int dragType, ClickType clickType, EntityPlayer player) {
		if (slot == OUTPUT_SLOT) {
			this.outputUpdatesDisabeled = true;
			if (!this.world.isRemote) {
				ItemStack output = DisenchantingUtils.disenchantInInventory(this.getTableInventory(), false, this.world,
						this.position, this.random);
				this.getTableInventory().setOutputStack(output);
			}
			this.detectAndSendChanges();
			// because of desync client and server there is a ghost item created here,
			// which can lead to item duplication
		}
		ItemStack result = super.slotClick(slot, dragType, clickType, player);
		this.outputUpdatesDisabeled = false;
		return result;
	}

}

@@ -172,31 +172,115 @@
 .player.
-InventoryPlayer
+EntityPlayerMP;%0Aimport net.minecraft.entity.player.InventoryPlayer;%0Aimport net.minecraft.init.Items
 ;%0Aimport
@@ -1608,16 +1608,53 @@
 slot) %7B%0A
+%09%09if (!this.outputUpdatesDisabeled)%0A%09
 %09%09this.u
@@ -1665,16 +1665,20 @@
 eOutput(
+true
 );%0A%09%09thi
@@ -1733,16 +1733,45 @@
 eOutput(
+boolean ignoreEnchantmentLoss
 ) %7B%0A%09%09if
@@ -1796,40 +1796,8 @@
 mote
- && !this.outputUpdatesDisabeled
 ) %7B%0A
@@ -2123,20 +2123,37 @@
 e,%0A%09%09%09%09%09
-true
+ignoreEnchantmentLoss
 , this.w
@@ -2185,24 +2185,177 @@
 .random)) %7B%0A
+%09%09%09%09if (target.getItem().equals(Items.ENCHANTED_BOOK) && DisenchantingUtils.getEnchantmentList(target) == null)%0A%09%09%09%09%09target = new ItemStack(Items.BOOK);%0A
 %09%09%09%09if (!(It
@@ -2762,105 +2762,402 @@
 SLOT
-) %7B%0A%09%09%09this.outputUpdatesDisabeled = true;%0A%09%09%09if (!this.world.isRemote) %7B%0A%09%09%09%09ItemStack output = 
+ && !this.world.isRemote && clickType != ClickType.CLONE) %7B%0A%09%09%09this.outputUpdatesDisabeled = true;%0A%09%09%09this.updateOutput(false);%0A%09%09%09boolean wasEmpty = this.getTableInventory().getOutputStack().isEmpty();%0A%09%09%09ItemStack result = super.slotClick(slot, dragType, clickType, player);%0A%09%09%09this.outputUpdatesDisabeled = false;%0A%09%09%09if (this.getTableInventory().getOutputStack().isEmpty() && !wasEmpty)%0A%09%09%09%09
 Dise
@@ -3241,15 +3241,9 @@
 rld,
-%0A%09%09%09%09%09%09
+ 
 this
@@ -3274,345 +3274,223 @@
 %0A%09%09%09
-%09this.getTableInventory().setOutputStack(output);%0A%09%09%09%7D%0A%09%09%09this.detectAndSendChanges();%0A%09%09%09// because of desync client and server there is a ghost item created here,%0A%09%09%09// which can lead to item duplication%0A%09%09%7D%0A%09%09ItemStack result = super.slotClick(slot, dragType, clickType, player);%0A%09%09this.outputUpdatesDisabeled = false;%0A%09%09return result
+else%0A%09%09%09%09this.updateOutput(true);%0A%09%09%09if (player instanceof EntityPlayerMP)%0A%09%09%09%09((EntityPlayerMP) player).sendContainerToPlayer(this);%0A%09%09%09return result;%0A%09%09%7D%0A%09%09return super.slotClick(slot, dragType, clickType, player)
 ;%0A%09%7D

Fix item duplication and other issues with slotClick