From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: willies952002 <admin@domnian.com>
Date: Fri, 16 Aug 2019 22:18:35 -0400
Subject: [PATCH] Fix Bukkit.createInventory() with type LECTERN

This fixes an issue with Bukkit which makes it possible to open a Lectern interface, but not be able to interact with it (e.g.: change pages). The following changes had to be made:

nms.TileEntityLectern:
- Add `virtual` flag, this is used to stop calls that would attempt to update a block which we do not have, as well as used in the following change.

nms.TileEntityLectern$LecternInventory
- in `a(EntityHuman)`, add `(TileEntityLectern.this.virtual && TileEntityLectern.this.hasBook()) ||` to short-circuit the "can use" logic
- Add `getLectern()` method for use in the following change.

obc.e.CraftHumanEntity#openInventory(Inventory):
- Check if the wrapped inventory is a TileEntityLectern.LecternInventory, and get the Lectern from that

obc.i.u.CraftTileInventoryConverter$Lectern:
- Mark the created lectern as "virtual"
- Override `getInventory(IInventory)` to return a CraftInventoryLectern.

This patch is licensed under the MIT License.
License: https://opensource.org/licenses/MIT

diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLectern.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLectern.java
index 89618f652b5eea4a380b0f00a5e4f8007495a0ef..94562f7b0f5cde9f8b4a163cc2b8cf7ab6c5d897 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLectern.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLectern.java
@@ -44,6 +44,11 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
     // CraftBukkit start - add fields and methods
     public final IInventory inventory = new LecternInventory();
     public class LecternInventory implements IInventory {
+        // EMC start
+        public TileEntityLectern getLectern() {
+            return TileEntityLectern.this;
+        }
+        // EMC end
 
         public List<HumanEntity> transaction = new ArrayList<>();
         private int maxStack = 1;
@@ -101,7 +106,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
 
         @Override
         public ItemStack splitStack(int i, int j) {
-            if (i == 0) {
+            if (i == 0 && !TileEntityLectern.this.virtual) { // EMC
                 ItemStack itemstack = TileEntityLectern.this.book.cloneAndSubtract(j);
 
                 if (TileEntityLectern.this.book.isEmpty()) {
@@ -116,7 +121,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
 
         @Override
         public ItemStack splitWithoutUpdate(int i) {
-            if (i == 0) {
+            if (i == 0 && !TileEntityLectern.this.virtual) { // EMC
                 ItemStack itemstack = TileEntityLectern.this.book;
 
                 TileEntityLectern.this.book = ItemStack.b;
@@ -151,7 +156,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
 
         @Override
         public boolean a(EntityHuman entityhuman) {
-            return TileEntityLectern.this.world.getTileEntity(TileEntityLectern.this.position) != TileEntityLectern.this ? false : (entityhuman.h((double) TileEntityLectern.this.position.getX() + 0.5D, (double) TileEntityLectern.this.position.getY() + 0.5D, (double) TileEntityLectern.this.position.getZ() + 0.5D) > 64.0D ? false : TileEntityLectern.this.hasBook());
+            return (TileEntityLectern.this.virtual && TileEntityLectern.this.hasBook()) || TileEntityLectern.this.world.getTileEntity(TileEntityLectern.this.position) != TileEntityLectern.this ? false : (entityhuman.h((double) TileEntityLectern.this.position.getX() + 0.5D, (double) TileEntityLectern.this.position.getY() + 0.5D, (double) TileEntityLectern.this.position.getZ() + 0.5D) > 64.0D ? false : TileEntityLectern.this.hasBook()); // EMC
         }
 
         @Override
@@ -184,6 +189,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
     private ItemStack book;
     private int page;
     private int maxPage;
+    public boolean virtual = false; // EMC
 
     public TileEntityLectern() {
         super(TileEntityTypes.LECTERN);
@@ -205,6 +211,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
     }
 
     private void k() {
+        if (this.virtual) return; // EMC
         this.page = 0;
         this.maxPage = 0;
         BlockLectern.setHasBook(this.getWorld(), this.getPosition(), this.getBlock(), false);
@@ -222,6 +229,7 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
 
         if (j != this.page) {
             this.page = j;
+            if (this.virtual) return; // EMC
             this.update();
             if (this.world != null) BlockLectern.a(this.getWorld(), this.getPosition(), this.getBlock()); // CraftBukkit
         }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index b99423b3b413fc6364c6530a99e3c74dd406e1b4..011426d0ce66299e50bd6dd2295e27bb2a873eb3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -31,6 +31,7 @@ import net.minecraft.world.level.block.BlockWorkbench;
 import net.minecraft.world.level.block.Blocks;
 import net.minecraft.world.level.block.entity.TileEntity;
 import net.minecraft.world.level.block.entity.TileEntityContainer;
+import net.minecraft.world.level.block.entity.TileEntityLectern; // EMC
 import net.minecraft.world.level.block.entity.TileEntitySign;
 import net.minecraft.world.level.block.state.IBlockData;
 import org.bukkit.GameMode;
@@ -301,6 +302,11 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
             if (craft.getInventory() instanceof ITileInventory) {
                 iinventory = (ITileInventory) craft.getInventory();
             }
+            // EMC start
+            if (craft.getInventory() instanceof TileEntityLectern.LecternInventory) {
+                iinventory = ((TileEntityLectern.LecternInventory)craft.getInventory()).getLectern();
+            }
+            // EMC end
         }
 
         if (iinventory instanceof ITileInventory) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
index 2bd4e644ffbde2e1133b25824a2829bc6b33fa84..06cd47ea0ab93ba9ef92e32a34118102070b582a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
@@ -159,8 +159,19 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
 
         @Override
         public IInventory getTileEntity() {
-            return new TileEntityLectern().inventory;
+            // EMC start
+            TileEntityLectern lectern = new TileEntityLectern();
+            lectern.virtual = true;
+            return lectern.inventory;
+            // EMC end
         }
+
+        // EMC start
+        @Override
+        public Inventory getInventory(IInventory tileEntity) {
+            return new org.bukkit.craftbukkit.inventory.CraftInventoryLectern(tileEntity);
+        }
+        // EMC end
     }
 
     public static class Smoker extends CraftTileInventoryConverter {
