From a10c61168ad158d352711e0cfbb3fc227bc5f309 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 25 Nov 2016 22:23:18 -0500 Subject: [PATCH] Add modules for 1.4.5 through 1.10, flesh out readme --- 1_4_5/pom.xml | 28 ++ .../internal/v1_4_5/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_4_5/InventoryAccess.java | 79 +++++ .../internal/v1_4_5/PlayerDataManager.java | 62 ++++ .../internal/v1_4_5/SilentContainerChest.java | 46 +++ .../internal/v1_4_5/SpecialEnderChest.java | 128 ++++++++ .../v1_4_5/SpecialPlayerInventory.java | 237 ++++++++++++++ 1_4_6/pom.xml | 28 ++ .../internal/v1_4_6/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_4_6/InventoryAccess.java | 79 +++++ .../internal/v1_4_6/PlayerDataManager.java | 62 ++++ .../internal/v1_4_6/SilentContainerChest.java | 46 +++ .../internal/v1_4_6/SpecialEnderChest.java | 128 ++++++++ .../v1_4_6/SpecialPlayerInventory.java | 229 ++++++++++++++ README | 13 - README.MD | 139 ++++++++ assembly/pom.xml | 131 ++++++++ pom.xml | 44 ++- v1_10_R1/pom.xml | 28 ++ .../internal/v1_10_R1/AnySilentContainer.java | 206 ++++++++++++ .../internal/v1_10_R1/InventoryAccess.java | 79 +++++ .../internal/v1_10_R1/PlayerDataManager.java | 64 ++++ .../v1_10_R1/SilentContainerChest.java | 46 +++ .../internal/v1_10_R1/SpecialEnderChest.java | 105 +++++++ .../v1_10_R1/SpecialPlayerInventory.java | 296 ++++++++++++++++++ v1_4_R1/pom.xml | 28 ++ .../internal/v1_4_R1/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_4_R1/InventoryAccess.java | 79 +++++ .../internal/v1_4_R1/PlayerDataManager.java | 63 ++++ .../v1_4_R1/SilentContainerChest.java | 46 +++ .../internal/v1_4_R1/SpecialEnderChest.java | 128 ++++++++ .../v1_4_R1/SpecialPlayerInventory.java | 237 ++++++++++++++ v1_5_R2/pom.xml | 28 ++ .../internal/v1_5_R2/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_5_R2/InventoryAccess.java | 79 +++++ .../internal/v1_5_R2/PlayerDataManager.java | 62 ++++ .../v1_5_R2/SilentContainerChest.java | 46 +++ .../internal/v1_5_R2/SpecialEnderChest.java | 129 ++++++++ .../v1_5_R2/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_5_R3/pom.xml | 28 ++ .../internal/v1_5_R3/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_5_R3/InventoryAccess.java | 79 +++++ .../internal/v1_5_R3/PlayerDataManager.java | 62 ++++ .../v1_5_R3/SilentContainerChest.java | 46 +++ .../internal/v1_5_R3/SpecialEnderChest.java | 129 ++++++++ .../v1_5_R3/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_6_R1/pom.xml | 28 ++ .../internal/v1_6_R1/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_6_R1/InventoryAccess.java | 79 +++++ .../internal/v1_6_R1/PlayerDataManager.java | 62 ++++ .../v1_6_R1/SilentContainerChest.java | 46 +++ .../internal/v1_6_R1/SpecialEnderChest.java | 129 ++++++++ .../v1_6_R1/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_6_R2/pom.xml | 28 ++ .../internal/v1_6_R2/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_6_R2/InventoryAccess.java | 79 +++++ .../internal/v1_6_R2/PlayerDataManager.java | 62 ++++ .../v1_6_R2/SilentContainerChest.java | 46 +++ .../internal/v1_6_R2/SpecialEnderChest.java | 129 ++++++++ .../v1_6_R2/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_6_R3/pom.xml | 28 ++ .../internal/v1_6_R3/AnySilentContainer.java | 168 ++++++++++ .../internal/v1_6_R3/InventoryAccess.java | 79 +++++ .../internal/v1_6_R3/PlayerDataManager.java | 62 ++++ .../v1_6_R3/SilentContainerChest.java | 46 +++ .../internal/v1_6_R3/SpecialEnderChest.java | 129 ++++++++ .../v1_6_R3/SpecialPlayerInventory.java | 226 +++++++++++++ v1_7_R1/pom.xml | 28 ++ .../internal/v1_7_R1/AnySilentContainer.java | 169 ++++++++++ .../internal/v1_7_R1/InventoryAccess.java | 79 +++++ .../internal/v1_7_R1/PlayerDataManager.java | 63 ++++ .../v1_7_R1/SilentContainerChest.java | 46 +++ .../internal/v1_7_R1/SpecialEnderChest.java | 129 ++++++++ .../v1_7_R1/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_7_R2/pom.xml | 28 ++ .../internal/v1_7_R2/AnySilentContainer.java | 169 ++++++++++ .../internal/v1_7_R2/InventoryAccess.java | 79 +++++ .../internal/v1_7_R2/PlayerDataManager.java | 64 ++++ .../v1_7_R2/SilentContainerChest.java | 46 +++ .../internal/v1_7_R2/SpecialEnderChest.java | 129 ++++++++ .../v1_7_R2/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_7_R3/pom.xml | 28 ++ .../internal/v1_7_R3/AnySilentContainer.java | 169 ++++++++++ .../internal/v1_7_R3/InventoryAccess.java | 79 +++++ .../internal/v1_7_R3/PlayerDataManager.java | 63 ++++ .../v1_7_R3/SilentContainerChest.java | 45 +++ .../internal/v1_7_R3/SpecialEnderChest.java | 129 ++++++++ .../v1_7_R3/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_7_R4/pom.xml | 28 ++ .../internal/v1_7_R4/AnySilentContainer.java | 169 ++++++++++ .../internal/v1_7_R4/InventoryAccess.java | 79 +++++ .../internal/v1_7_R4/PlayerDataManager.java | 63 ++++ .../v1_7_R4/SilentContainerChest.java | 46 +++ .../internal/v1_7_R4/SpecialEnderChest.java | 129 ++++++++ .../v1_7_R4/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_8_R1/pom.xml | 28 ++ .../internal/v1_8_R1/AnySilentContainer.java | 205 ++++++++++++ .../internal/v1_8_R1/InventoryAccess.java | 79 +++++ .../internal/v1_8_R1/PlayerDataManager.java | 64 ++++ .../v1_8_R1/SilentContainerChest.java | 46 +++ .../internal/v1_8_R1/SpecialEnderChest.java | 86 +++++ .../v1_8_R1/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_8_R2/pom.xml | 28 ++ .../internal/v1_8_R2/AnySilentContainer.java | 205 ++++++++++++ .../internal/v1_8_R2/InventoryAccess.java | 79 +++++ .../internal/v1_8_R2/PlayerDataManager.java | 64 ++++ .../v1_8_R2/SilentContainerChest.java | 46 +++ .../internal/v1_8_R2/SpecialEnderChest.java | 86 +++++ .../v1_8_R2/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_8_R3/pom.xml | 28 ++ .../internal/v1_8_R3/AnySilentContainer.java | 205 ++++++++++++ .../internal/v1_8_R3/InventoryAccess.java | 79 +++++ .../internal/v1_8_R3/PlayerDataManager.java | 64 ++++ .../v1_8_R3/SilentContainerChest.java | 46 +++ .../internal/v1_8_R3/SpecialEnderChest.java | 86 +++++ .../v1_8_R3/SpecialPlayerInventory.java | 229 ++++++++++++++ v1_9_R1/pom.xml | 27 ++ .../internal/v1_9_R1/AnySilentContainer.java | 205 ++++++++++++ .../internal/v1_9_R1/InventoryAccess.java | 79 +++++ .../internal/v1_9_R1/PlayerDataManager.java | 64 ++++ .../v1_9_R1/SilentContainerChest.java | 46 +++ .../internal/v1_9_R1/SpecialEnderChest.java | 86 +++++ .../v1_9_R1/SpecialPlayerInventory.java | 290 +++++++++++++++++ v1_9_R2/pom.xml | 28 ++ .../internal/v1_9_R2/AnySilentContainer.java | 205 ++++++++++++ .../internal/v1_9_R2/InventoryAccess.java | 79 +++++ .../internal/v1_9_R2/PlayerDataManager.java | 64 ++++ .../v1_9_R2/SilentContainerChest.java | 46 +++ .../internal/v1_9_R2/SpecialEnderChest.java | 86 +++++ .../v1_9_R2/SpecialPlayerInventory.java | 296 ++++++++++++++++++ 130 files changed, 13859 insertions(+), 15 deletions(-) create mode 100644 1_4_5/pom.xml create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/AnySilentContainer.java create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/InventoryAccess.java create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/PlayerDataManager.java create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SilentContainerChest.java create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialEnderChest.java create mode 100644 1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialPlayerInventory.java create mode 100644 1_4_6/pom.xml create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/AnySilentContainer.java create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/InventoryAccess.java create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/PlayerDataManager.java create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SilentContainerChest.java create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialEnderChest.java create mode 100644 1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialPlayerInventory.java delete mode 100644 README create mode 100644 README.MD create mode 100644 v1_10_R1/pom.xml create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/InventoryAccess.java create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/PlayerDataManager.java create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialEnderChest.java create mode 100644 v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialPlayerInventory.java create mode 100644 v1_4_R1/pom.xml create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/AnySilentContainer.java create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/InventoryAccess.java create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/PlayerDataManager.java create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SilentContainerChest.java create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialEnderChest.java create mode 100644 v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialPlayerInventory.java create mode 100644 v1_5_R2/pom.xml create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/AnySilentContainer.java create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/InventoryAccess.java create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/PlayerDataManager.java create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SilentContainerChest.java create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialEnderChest.java create mode 100644 v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialPlayerInventory.java create mode 100644 v1_5_R3/pom.xml create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/AnySilentContainer.java create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/InventoryAccess.java create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/PlayerDataManager.java create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SilentContainerChest.java create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialEnderChest.java create mode 100644 v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialPlayerInventory.java create mode 100644 v1_6_R1/pom.xml create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/AnySilentContainer.java create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/InventoryAccess.java create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/PlayerDataManager.java create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SilentContainerChest.java create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialEnderChest.java create mode 100644 v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialPlayerInventory.java create mode 100644 v1_6_R2/pom.xml create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/AnySilentContainer.java create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/InventoryAccess.java create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/PlayerDataManager.java create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SilentContainerChest.java create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialEnderChest.java create mode 100644 v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialPlayerInventory.java create mode 100644 v1_6_R3/pom.xml create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/AnySilentContainer.java create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/InventoryAccess.java create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/PlayerDataManager.java create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SilentContainerChest.java create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialEnderChest.java create mode 100644 v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialPlayerInventory.java create mode 100644 v1_7_R1/pom.xml create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/AnySilentContainer.java create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/InventoryAccess.java create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/PlayerDataManager.java create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SilentContainerChest.java create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialEnderChest.java create mode 100644 v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialPlayerInventory.java create mode 100644 v1_7_R2/pom.xml create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/AnySilentContainer.java create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/InventoryAccess.java create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/PlayerDataManager.java create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SilentContainerChest.java create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialEnderChest.java create mode 100644 v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialPlayerInventory.java create mode 100644 v1_7_R3/pom.xml create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/AnySilentContainer.java create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/InventoryAccess.java create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/PlayerDataManager.java create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SilentContainerChest.java create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialEnderChest.java create mode 100644 v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialPlayerInventory.java create mode 100644 v1_7_R4/pom.xml create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/AnySilentContainer.java create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/InventoryAccess.java create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/PlayerDataManager.java create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SilentContainerChest.java create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialEnderChest.java create mode 100644 v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialPlayerInventory.java create mode 100644 v1_8_R1/pom.xml create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/InventoryAccess.java create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/PlayerDataManager.java create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialEnderChest.java create mode 100644 v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialPlayerInventory.java create mode 100644 v1_8_R2/pom.xml create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/InventoryAccess.java create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/PlayerDataManager.java create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialEnderChest.java create mode 100644 v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialPlayerInventory.java create mode 100644 v1_8_R3/pom.xml create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/InventoryAccess.java create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java create mode 100644 v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java create mode 100644 v1_9_R1/pom.xml create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/InventoryAccess.java create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/PlayerDataManager.java create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialEnderChest.java create mode 100644 v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialPlayerInventory.java create mode 100644 v1_9_R2/pom.xml create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/InventoryAccess.java create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/PlayerDataManager.java create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialEnderChest.java create mode 100644 v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialPlayerInventory.java diff --git a/1_4_5/pom.xml b/1_4_5/pom.xml new file mode 100644 index 0000000..0abd40e --- /dev/null +++ b/1_4_5/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_4_5 + OpenInvAdapter1_4_5 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.4.5-R1.0 + provided + + + + diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/AnySilentContainer.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/AnySilentContainer.java new file mode 100644 index 0000000..f084a76 --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_4_5.AxisAlignedBB; +import net.minecraft.server.v1_4_5.BlockEnderChest; +import net.minecraft.server.v1_4_5.EntityOcelot; +import net.minecraft.server.v1_4_5.EntityPlayer; +import net.minecraft.server.v1_4_5.IInventory; +import net.minecraft.server.v1_4_5.InventoryEnderChest; +import net.minecraft.server.v1_4_5.InventoryLargeChest; +import net.minecraft.server.v1_4_5.Packet100OpenWindow; +import net.minecraft.server.v1_4_5.TileEntityChest; +import net.minecraft.server.v1_4_5.TileEntityEnderChest; +import net.minecraft.server.v1_4_5.World; + +import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.netServerHandler.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize())); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/InventoryAccess.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/InventoryAccess.java new file mode 100644 index 0000000..4b61708 --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_5.IInventory; + +import org.bukkit.craftbukkit.v1_4_5.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/PlayerDataManager.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/PlayerDataManager.java new file mode 100644 index 0000000..08500e7 --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_4_5.EntityPlayer; +import net.minecraft.server.v1_4_5.ItemInWorldManager; +import net.minecraft.server.v1_4_5.MinecraftServer; + +import org.bukkit.craftbukkit.v1_4_5.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new ItemInWorldManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SilentContainerChest.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SilentContainerChest.java new file mode 100644 index 0000000..0405f7a --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +// Volatile +import net.minecraft.server.v1_4_5.ContainerChest; +import net.minecraft.server.v1_4_5.EntityHuman; +import net.minecraft.server.v1_4_5.IInventory; +import net.minecraft.server.v1_4_5.ItemStack; +import net.minecraft.server.v1_4_5.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.f(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialEnderChest.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialEnderChest.java new file mode 100644 index 0000000..abedc51 --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialEnderChest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_4_5.IInventory; +import net.minecraft.server.v1_4_5.InventoryEnderChest; +import net.minecraft.server.v1_4_5.InventorySubcontainer; +import net.minecraft.server.v1_4_5.ItemStack; + +import org.bukkit.craftbukkit.v1_4_5.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_5.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialPlayerInventory.java b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialPlayerInventory.java new file mode 100644 index 0000000..b989c48 --- /dev/null +++ b/1_4_5/src/main/java/com/lishid/openinv/internal/v1_4_5/SpecialPlayerInventory.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_5; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_5.ItemStack; +import net.minecraft.server.v1_4_5.PlayerInventory; + +import org.bukkit.craftbukkit.v1_4_5.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_5.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } + else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + else { + return null; + } + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + else { + return null; + } + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) + return i - 27; + else + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) + return 3; + if (i == 1) + return 2; + if (i == 2) + return 1; + if (i == 3) + return 0; + else + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/1_4_6/pom.xml b/1_4_6/pom.xml new file mode 100644 index 0000000..fb3c735 --- /dev/null +++ b/1_4_6/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_4_6 + OpenInvAdapter1_4_6 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.4.6-R0.3 + provided + + + + diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/AnySilentContainer.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/AnySilentContainer.java new file mode 100644 index 0000000..9e899a2 --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_4_6.AxisAlignedBB; +import net.minecraft.server.v1_4_6.BlockEnderChest; +import net.minecraft.server.v1_4_6.EntityOcelot; +import net.minecraft.server.v1_4_6.EntityPlayer; +import net.minecraft.server.v1_4_6.IInventory; +import net.minecraft.server.v1_4_6.InventoryEnderChest; +import net.minecraft.server.v1_4_6.InventoryLargeChest; +import net.minecraft.server.v1_4_6.Packet100OpenWindow; +import net.minecraft.server.v1_4_6.TileEntityChest; +import net.minecraft.server.v1_4_6.TileEntityEnderChest; +import net.minecraft.server.v1_4_6.World; + +import org.bukkit.craftbukkit.v1_4_6.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize())); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/InventoryAccess.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/InventoryAccess.java new file mode 100644 index 0000000..69a3374 --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_6.IInventory; + +import org.bukkit.craftbukkit.v1_4_6.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/PlayerDataManager.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/PlayerDataManager.java new file mode 100644 index 0000000..b768876 --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_4_6.EntityPlayer; +import net.minecraft.server.v1_4_6.MinecraftServer; +import net.minecraft.server.v1_4_6.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_4_6.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SilentContainerChest.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SilentContainerChest.java new file mode 100644 index 0000000..c613a7b --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +// Volatile +import net.minecraft.server.v1_4_6.ContainerChest; +import net.minecraft.server.v1_4_6.EntityHuman; +import net.minecraft.server.v1_4_6.IInventory; +import net.minecraft.server.v1_4_6.ItemStack; +import net.minecraft.server.v1_4_6.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.f(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialEnderChest.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialEnderChest.java new file mode 100644 index 0000000..b863941 --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialEnderChest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_4_6.IInventory; +import net.minecraft.server.v1_4_6.InventoryEnderChest; +import net.minecraft.server.v1_4_6.InventorySubcontainer; +import net.minecraft.server.v1_4_6.ItemStack; + +import org.bukkit.craftbukkit.v1_4_6.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_4_6.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_6.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialPlayerInventory.java b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialPlayerInventory.java new file mode 100644 index 0000000..42fa710 --- /dev/null +++ b/1_4_6/src/main/java/com/lishid/openinv/internal/v1_4_6/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_6; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_6.ItemStack; +import net.minecraft.server.v1_4_6.PlayerInventory; + +import org.bukkit.craftbukkit.v1_4_6.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_6.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/README b/README deleted file mode 100644 index ebd75f3..0000000 --- a/README +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (C) 2011-2016 lishid. All rights reserved. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 3. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..dcd7296 --- /dev/null +++ b/README.MD @@ -0,0 +1,139 @@ +## About +OpenInv is a [Bukkit plugin](https://dev.bukkit.org/bukkit-plugins/openinv/) which allows users to open and edit anyone's inventory or ender chest - online or not! + +## Features +- **OpenInv**: Open anyone's inventory, even if they're offline. + - Read-only mode! No edits allowed! Don't grant the permission `OpenInv.editinv` + - Cross-world support! Don't grant `OpenInv.crossworld` + - No self-opening! Don't grant `OpenInv.openself` + - Drop items as the player! Place items in the unused slots to the right of the armor to drop them +- **OpenEnder**: Open anyone's inventory, even if they're offline. + - Read-only mode! No edits allowed! Don't grant `OpenInv.editender` + - Cross-world support! Don't grant `OpenInv.crossworld` + - No self-opening! Don't grant `OpenInv.openself` +- **SilentChest**: Open containers without displaying an animation or making sound. +- **AnyChest**: Open containers, even if blocked by ocelots or blocks. + +## Commands + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandAliasesDescription
/openinv [player]oi, inv, openOpen a player's inventory. If unspecified, will select last player opened or own if none opened previously.
/openender [player]oeOpen a player's ender chest. If unspecified, will select last player opened or own if none opened previously.
/searchinv <item> [minAmount]siLists all online players that have a certain item in their inventory.
/searchender <item> [minAmount]seLists all online players that have a certain item in their ender chest.
/anychest [check]acCheck or toggle the AnyChest function, allowing opening blocked containers.
/silentchest [check]scCheck or toggle the SilentChest function, allowing opening containers silently.
+ +## Permissions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NodeDescription
OpenInv.*Gives permission to use all of OpenInv.
OpenInv.openinvRequired to use /openinv.
OpenInv.openselfRequired to open own inventory.
OpenInv.editinvRequired to make changes to open inventories.
OpenInv.openenderRequired to use /openender.
OpenInv.editinvRequired to make changes to open ender chests.
OpenInv.openenderallAllows users to open others' ender chests. Without it, users can only open their own.
OpenInv.exemptPrevents the player's inventory being opened by others.
OpenInv.overrideAllows bypassing of the exempt permission.
OpenInv.crossworldAllows cross-world usage of /openinv and /openender.
OpenInv.searchRequired to use /searchinv and /searchender.
OpenInv.anychestRequired to use /anychest.
OpenInv.silentRequired to use /silentchest.
+ +## For Developers +To compile, the relevant Craftbukkit/Spigot jars must be installed in your local repository using the install plugin. +Ex: `mvn install:install-file -Dpackaging=jar -Dfile=spigot-1.11-R0.1-SNAPSHOT.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.11-R0.1-SNAPSHOT` + +Compiling OpenInv for a specific version is very easy - just compile the correct module. + +Compiling for a set of versions is slightly more complex. You'll need to use a profile for the versions you want to compile. Provided profiles are latest, modern (versions 1.8+), and all. For more information, check out the [official guide](http://maven.apache.org/guides/introduction/introduction-to-profiles.html). + +## License +``` +Copyright (C) 2011-2014 lishid. All rights reserved. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +``` \ No newline at end of file diff --git a/assembly/pom.xml b/assembly/pom.xml index 86563e3..17e12af 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -24,9 +24,140 @@ + + modern + + + com.lishid + openinvadapter1_8_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_8_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_8_R3 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_9_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_9_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_10_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_11_R1 + 1.0-SNAPSHOT + + + + all + + com.lishid + openinvadapter1_4_5 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_4_6 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_4_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_5_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_5_R3 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_6_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_6_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_6_R3 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_7_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_7_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_7_R3 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_7_R4 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_8_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_8_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_8_R3 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_9_R1 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_9_R2 + 1.0-SNAPSHOT + + + com.lishid + openinvadapter1_10_R1 + 1.0-SNAPSHOT + com.lishid openinvadapter1_11_R1 diff --git a/pom.xml b/pom.xml index 8bd482c..97b1381 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,5 @@ - + + 4.0.0 com.lishid openinv @@ -54,12 +54,52 @@ + + modern + + + modern + true + + + + v1_8_R1 + v1_8_R2 + v1_8_R3 + v1_9_R1 + v1_9_R2 + v1_10_R1 + v1_11_R1 + + + all true + 1_4_5 + 1_4_6 + v1_4_R1 + + v1_5_R2 + v1_5_R3 + + v1_6_R1 + v1_6_R2 + v1_6_R3 + + v1_7_R1 + v1_7_R2 + v1_7_R3 + v1_7_R4 + v1_8_R1 + v1_8_R2 + v1_8_R3 + v1_9_R1 + v1_9_R2 + v1_10_R1 v1_11_R1 diff --git a/v1_10_R1/pom.xml b/v1_10_R1/pom.xml new file mode 100644 index 0000000..bf3d81b --- /dev/null +++ b/v1_10_R1/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_10_R1 + OpenInvAdapter1_10_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.10-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java new file mode 100644 index 0000000..8e3a01c --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_10_R1.AxisAlignedBB; +import net.minecraft.server.v1_10_R1.Block; +import net.minecraft.server.v1_10_R1.BlockChest; +import net.minecraft.server.v1_10_R1.BlockChest.Type; +import net.minecraft.server.v1_10_R1.BlockEnderChest; +import net.minecraft.server.v1_10_R1.BlockPosition; +import net.minecraft.server.v1_10_R1.Entity; +import net.minecraft.server.v1_10_R1.EntityOcelot; +import net.minecraft.server.v1_10_R1.EntityPlayer; +import net.minecraft.server.v1_10_R1.EnumDirection; +import net.minecraft.server.v1_10_R1.IInventory; +import net.minecraft.server.v1_10_R1.ITileInventory; +import net.minecraft.server.v1_10_R1.InventoryEnderChest; +import net.minecraft.server.v1_10_R1.InventoryLargeChest; +import net.minecraft.server.v1_10_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_10_R1.StatisticList; +import net.minecraft.server.v1_10_R1.TileEntity; +import net.minecraft.server.v1_10_R1.TileEntityChest; +import net.minecraft.server.v1_10_R1.TileEntityEnderChest; +import net.minecraft.server.v1_10_R1.World; + +import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).m(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).l() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.X); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.X); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + + if (((BlockChest) block).g == Type.BASIC) + player.b(StatisticList.ac); + else if (((BlockChest) block).g == Type.TRAP) { + player.b(StatisticList.W); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/InventoryAccess.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/InventoryAccess.java new file mode 100644 index 0000000..a827864 --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_10_R1.IInventory; + +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/PlayerDataManager.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/PlayerDataManager.java new file mode 100644 index 0000000..cecd3c7 --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_10_R1.EntityPlayer; +import net.minecraft.server.v1_10_R1.MinecraftServer; +import net.minecraft.server.v1_10_R1.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_10_R1.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java new file mode 100644 index 0000000..0185618 --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +// Volatile +import net.minecraft.server.v1_10_R1.ContainerChest; +import net.minecraft.server.v1_10_R1.EntityHuman; +import net.minecraft.server.v1_10_R1.IInventory; +import net.minecraft.server.v1_10_R1.ItemStack; +import net.minecraft.server.v1_10_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // Send close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialEnderChest.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialEnderChest.java new file mode 100644 index 0000000..aabdde3 --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialEnderChest.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_10_R1.IInventory; +import net.minecraft.server.v1_10_R1.InventoryEnderChest; +import net.minecraft.server.v1_10_R1.InventorySubcontainer; +import net.minecraft.server.v1_10_R1.ItemStack; + +import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + setItemArrays(this, enderChest.getContents()); + } + + private void setItemArrays(InventorySubcontainer subcontainer, ItemStack[] items) { + try { + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + // Access and replace main inventory array + Field field = InventorySubcontainer.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(subcontainer, items); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + setItemArrays(craftPlayer.getHandle().getEnderChest(), this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialPlayerInventory.java b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..db86309 --- /dev/null +++ b/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SpecialPlayerInventory.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_10_R1; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_10_R1.EntityHuman; +import net.minecraft.server.v1_10_R1.ItemStack; +import net.minecraft.server.v1_10_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[4]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + setItemArrays(this, player.inventory.items, player.inventory.armor, player.inventory.extraSlots); + } + + private void setItemArrays(PlayerInventory inventory, ItemStack[] items, ItemStack[] armor, + ItemStack[] extraSlots) { + try { + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + + // Access and replace main inventory array + Field field = PlayerInventory.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, items); + + // Access and replace armor inventory array + field = PlayerInventory.class.getField("armor"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, armor); + + // Access and replace offhand inventory array + field = PlayerInventory.class.getField("extraSlots"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, extraSlots); + + // Access and replace array containing all inventory arrays + field = PlayerInventory.class.getDeclaredField("g"); + field.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, new ItemStack[][] { items, armor, extraSlots }); + } catch (NoSuchFieldException e) { + // Unable to set final fields to item arrays, we're screwed. Noisily fail. + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + setItemArrays(this.player.inventory, items, armor, extraSlots); + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + System.arraycopy(extraSlots, 0, contents, items.length + armor.length, extraSlots.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 4; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // extraSlots is, for now, just an array with length 1. No need for special handling. + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].cloneAndSubtract(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + + @Override + public boolean a(EntityHuman entityhuman) { + return true; + } + +} diff --git a/v1_4_R1/pom.xml b/v1_4_R1/pom.xml new file mode 100644 index 0000000..0976b7e --- /dev/null +++ b/v1_4_R1/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_4_R1 + OpenInvAdapter1_4_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.4.7-R1.0 + provided + + + + diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/AnySilentContainer.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/AnySilentContainer.java new file mode 100644 index 0000000..1d0bee0 --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_4_R1.AxisAlignedBB; +import net.minecraft.server.v1_4_R1.BlockEnderChest; +import net.minecraft.server.v1_4_R1.EntityOcelot; +import net.minecraft.server.v1_4_R1.EntityPlayer; +import net.minecraft.server.v1_4_R1.IInventory; +import net.minecraft.server.v1_4_R1.InventoryEnderChest; +import net.minecraft.server.v1_4_R1.InventoryLargeChest; +import net.minecraft.server.v1_4_R1.Packet100OpenWindow; +import net.minecraft.server.v1_4_R1.TileEntityChest; +import net.minecraft.server.v1_4_R1.TileEntityEnderChest; +import net.minecraft.server.v1_4_R1.World; + +import org.bukkit.craftbukkit.v1_4_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize())); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/InventoryAccess.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/InventoryAccess.java new file mode 100644 index 0000000..0fd5d00 --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_R1.IInventory; + +import org.bukkit.craftbukkit.v1_4_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/PlayerDataManager.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/PlayerDataManager.java new file mode 100644 index 0000000..e92f7a2 --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/PlayerDataManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import net.minecraft.server.v1_4_R1.EntityPlayer; +import net.minecraft.server.v1_4_R1.MinecraftServer; +import net.minecraft.server.v1_4_R1.PlayerInteractManager; + +// Volatile +import org.bukkit.craftbukkit.v1_4_R1.CraftServer; + + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SilentContainerChest.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SilentContainerChest.java new file mode 100644 index 0000000..24c4018 --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +// Volatile +import net.minecraft.server.v1_4_R1.ContainerChest; +import net.minecraft.server.v1_4_R1.EntityHuman; +import net.minecraft.server.v1_4_R1.IInventory; +import net.minecraft.server.v1_4_R1.ItemStack; +import net.minecraft.server.v1_4_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.f(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialEnderChest.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialEnderChest.java new file mode 100644 index 0000000..ff5e70c --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialEnderChest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_4_R1.IInventory; +import net.minecraft.server.v1_4_R1.InventoryEnderChest; +import net.minecraft.server.v1_4_R1.InventorySubcontainer; +import net.minecraft.server.v1_4_R1.ItemStack; + +import org.bukkit.craftbukkit.v1_4_R1.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_4_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialPlayerInventory.java b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..e3c760e --- /dev/null +++ b/v1_4_R1/src/main/java/com/lishid/openinv/internal/v1_4_R1/SpecialPlayerInventory.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_4_R1; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_4_R1.ItemStack; +import net.minecraft.server.v1_4_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_4_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_4_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } + else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + else { + return null; + } + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + else { + return null; + } + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } + else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) + return i - 27; + else + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) + return 3; + if (i == 1) + return 2; + if (i == 2) + return 1; + if (i == 3) + return 0; + else + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_5_R2/pom.xml b/v1_5_R2/pom.xml new file mode 100644 index 0000000..e596180 --- /dev/null +++ b/v1_5_R2/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_5_R2 + OpenInvAdapter1_5_R2 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.5.1-R0.2 + provided + + + + diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/AnySilentContainer.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/AnySilentContainer.java new file mode 100644 index 0000000..d9137be --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_5_R2.AxisAlignedBB; +import net.minecraft.server.v1_5_R2.BlockEnderChest; +import net.minecraft.server.v1_5_R2.EntityOcelot; +import net.minecraft.server.v1_5_R2.EntityPlayer; +import net.minecraft.server.v1_5_R2.IInventory; +import net.minecraft.server.v1_5_R2.InventoryEnderChest; +import net.minecraft.server.v1_5_R2.InventoryLargeChest; +import net.minecraft.server.v1_5_R2.Packet100OpenWindow; +import net.minecraft.server.v1_5_R2.TileEntityChest; +import net.minecraft.server.v1_5_R2.TileEntityEnderChest; +import net.minecraft.server.v1_5_R2.World; + +import org.bukkit.craftbukkit.v1_5_R2.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/InventoryAccess.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/InventoryAccess.java new file mode 100644 index 0000000..b61d7ee --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_5_R2.IInventory; + +import org.bukkit.craftbukkit.v1_5_R2.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/PlayerDataManager.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/PlayerDataManager.java new file mode 100644 index 0000000..a6e8e7d --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_5_R2.EntityPlayer; +import net.minecraft.server.v1_5_R2.MinecraftServer; +import net.minecraft.server.v1_5_R2.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_5_R2.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SilentContainerChest.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SilentContainerChest.java new file mode 100644 index 0000000..60e085b --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +// Volatile +import net.minecraft.server.v1_5_R2.ContainerChest; +import net.minecraft.server.v1_5_R2.EntityHuman; +import net.minecraft.server.v1_5_R2.IInventory; +import net.minecraft.server.v1_5_R2.ItemStack; +import net.minecraft.server.v1_5_R2.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.g(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialEnderChest.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialEnderChest.java new file mode 100644 index 0000000..50355b7 --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_5_R2.IInventory; +import net.minecraft.server.v1_5_R2.InventoryEnderChest; +import net.minecraft.server.v1_5_R2.InventorySubcontainer; +import net.minecraft.server.v1_5_R2.ItemStack; + +import org.bukkit.craftbukkit.v1_5_R2.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_5_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_5_R2.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().c(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialPlayerInventory.java b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialPlayerInventory.java new file mode 100644 index 0000000..81c949e --- /dev/null +++ b/v1_5_R2/src/main/java/com/lishid/openinv/internal/v1_5_R2/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R2; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_5_R2.ItemStack; +import net.minecraft.server.v1_5_R2.PlayerInventory; + +import org.bukkit.craftbukkit.v1_5_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_5_R2.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_5_R3/pom.xml b/v1_5_R3/pom.xml new file mode 100644 index 0000000..4b2e345 --- /dev/null +++ b/v1_5_R3/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_5_R3 + OpenInvAdapter1_5_R3 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.5.2-R1.0 + provided + + + + diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/AnySilentContainer.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/AnySilentContainer.java new file mode 100644 index 0000000..ccc0490 --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_5_R3.AxisAlignedBB; +import net.minecraft.server.v1_5_R3.BlockEnderChest; +import net.minecraft.server.v1_5_R3.EntityOcelot; +import net.minecraft.server.v1_5_R3.EntityPlayer; +import net.minecraft.server.v1_5_R3.IInventory; +import net.minecraft.server.v1_5_R3.InventoryEnderChest; +import net.minecraft.server.v1_5_R3.InventoryLargeChest; +import net.minecraft.server.v1_5_R3.Packet100OpenWindow; +import net.minecraft.server.v1_5_R3.TileEntityChest; +import net.minecraft.server.v1_5_R3.TileEntityEnderChest; +import net.minecraft.server.v1_5_R3.World; + +import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/InventoryAccess.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/InventoryAccess.java new file mode 100644 index 0000000..1a0df32 --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_5_R3.IInventory; + +import org.bukkit.craftbukkit.v1_5_R3.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/PlayerDataManager.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/PlayerDataManager.java new file mode 100644 index 0000000..f77b8fd --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_5_R3.EntityPlayer; +import net.minecraft.server.v1_5_R3.MinecraftServer; +import net.minecraft.server.v1_5_R3.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_5_R3.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SilentContainerChest.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SilentContainerChest.java new file mode 100644 index 0000000..59c452e --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +// Volatile +import net.minecraft.server.v1_5_R3.ContainerChest; +import net.minecraft.server.v1_5_R3.EntityHuman; +import net.minecraft.server.v1_5_R3.IInventory; +import net.minecraft.server.v1_5_R3.ItemStack; +import net.minecraft.server.v1_5_R3.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { public IInventory inv; + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.g(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialEnderChest.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialEnderChest.java new file mode 100644 index 0000000..06c52b7 --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_5_R3.IInventory; +import net.minecraft.server.v1_5_R3.InventoryEnderChest; +import net.minecraft.server.v1_5_R3.InventorySubcontainer; +import net.minecraft.server.v1_5_R3.ItemStack; + +import org.bukkit.craftbukkit.v1_5_R3.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_5_R3.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().c(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialPlayerInventory.java b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialPlayerInventory.java new file mode 100644 index 0000000..f4668b9 --- /dev/null +++ b/v1_5_R3/src/main/java/com/lishid/openinv/internal/v1_5_R3/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_5_R3; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_5_R3.ItemStack; +import net.minecraft.server.v1_5_R3.PlayerInventory; + +import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_5_R3.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_6_R1/pom.xml b/v1_6_R1/pom.xml new file mode 100644 index 0000000..fa9b987 --- /dev/null +++ b/v1_6_R1/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_6_R1 + OpenInvAdapter1_6_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.6.1-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/AnySilentContainer.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/AnySilentContainer.java new file mode 100644 index 0000000..f685648 --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R1.AxisAlignedBB; +import net.minecraft.server.v1_6_R1.BlockEnderChest; +import net.minecraft.server.v1_6_R1.EntityOcelot; +import net.minecraft.server.v1_6_R1.EntityPlayer; +import net.minecraft.server.v1_6_R1.IInventory; +import net.minecraft.server.v1_6_R1.InventoryEnderChest; +import net.minecraft.server.v1_6_R1.InventoryLargeChest; +import net.minecraft.server.v1_6_R1.Packet100OpenWindow; +import net.minecraft.server.v1_6_R1.TileEntityChest; +import net.minecraft.server.v1_6_R1.TileEntityEnderChest; +import net.minecraft.server.v1_6_R1.World; + +import org.bukkit.craftbukkit.v1_6_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/InventoryAccess.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/InventoryAccess.java new file mode 100644 index 0000000..8d6dc65 --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R1.IInventory; + +import org.bukkit.craftbukkit.v1_6_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/PlayerDataManager.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/PlayerDataManager.java new file mode 100644 index 0000000..a7359c2 --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R1.EntityPlayer; +import net.minecraft.server.v1_6_R1.MinecraftServer; +import net.minecraft.server.v1_6_R1.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_6_R1.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SilentContainerChest.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SilentContainerChest.java new file mode 100644 index 0000000..92c910f --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +// Volatile +import net.minecraft.server.v1_6_R1.ContainerChest; +import net.minecraft.server.v1_6_R1.EntityHuman; +import net.minecraft.server.v1_6_R1.IInventory; +import net.minecraft.server.v1_6_R1.ItemStack; +import net.minecraft.server.v1_6_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.g(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialEnderChest.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialEnderChest.java new file mode 100644 index 0000000..d10b591 --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_6_R1.IInventory; +import net.minecraft.server.v1_6_R1.InventoryEnderChest; +import net.minecraft.server.v1_6_R1.InventorySubcontainer; +import net.minecraft.server.v1_6_R1.ItemStack; + +import org.bukkit.craftbukkit.v1_6_R1.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_6_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().c(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialPlayerInventory.java b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..dc397e4 --- /dev/null +++ b/v1_6_R1/src/main/java/com/lishid/openinv/internal/v1_6_R1/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R1; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R1.ItemStack; +import net.minecraft.server.v1_6_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_6_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_6_R2/pom.xml b/v1_6_R2/pom.xml new file mode 100644 index 0000000..3f4670e --- /dev/null +++ b/v1_6_R2/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_6_R2 + OpenInvAdapter1_6_R2 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.6.2-R1.0 + provided + + + + diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/AnySilentContainer.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/AnySilentContainer.java new file mode 100644 index 0000000..d39d49e --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R2.AxisAlignedBB; +import net.minecraft.server.v1_6_R2.BlockEnderChest; +import net.minecraft.server.v1_6_R2.EntityOcelot; +import net.minecraft.server.v1_6_R2.EntityPlayer; +import net.minecraft.server.v1_6_R2.IInventory; +import net.minecraft.server.v1_6_R2.InventoryEnderChest; +import net.minecraft.server.v1_6_R2.InventoryLargeChest; +import net.minecraft.server.v1_6_R2.Packet100OpenWindow; +import net.minecraft.server.v1_6_R2.TileEntityChest; +import net.minecraft.server.v1_6_R2.TileEntityEnderChest; +import net.minecraft.server.v1_6_R2.World; + +import org.bukkit.craftbukkit.v1_6_R2.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/InventoryAccess.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/InventoryAccess.java new file mode 100644 index 0000000..265202b --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R2.IInventory; + +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/PlayerDataManager.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/PlayerDataManager.java new file mode 100644 index 0000000..8401f1f --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R2.EntityPlayer; +import net.minecraft.server.v1_6_R2.MinecraftServer; +import net.minecraft.server.v1_6_R2.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_6_R2.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SilentContainerChest.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SilentContainerChest.java new file mode 100644 index 0000000..b8cb9dc --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +// Volatile +import net.minecraft.server.v1_6_R2.ContainerChest; +import net.minecraft.server.v1_6_R2.EntityHuman; +import net.minecraft.server.v1_6_R2.IInventory; +import net.minecraft.server.v1_6_R2.ItemStack; +import net.minecraft.server.v1_6_R2.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.g(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialEnderChest.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialEnderChest.java new file mode 100644 index 0000000..b7216ec --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_6_R2.IInventory; +import net.minecraft.server.v1_6_R2.InventoryEnderChest; +import net.minecraft.server.v1_6_R2.InventorySubcontainer; +import net.minecraft.server.v1_6_R2.ItemStack; + +import org.bukkit.craftbukkit.v1_6_R2.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_6_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().c(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialPlayerInventory.java b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialPlayerInventory.java new file mode 100644 index 0000000..3e766da --- /dev/null +++ b/v1_6_R2/src/main/java/com/lishid/openinv/internal/v1_6_R2/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R2; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R2.ItemStack; +import net.minecraft.server.v1_6_R2.PlayerInventory; + +import org.bukkit.craftbukkit.v1_6_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R2.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_6_R3/pom.xml b/v1_6_R3/pom.xml new file mode 100644 index 0000000..53b3b79 --- /dev/null +++ b/v1_6_R3/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_6_R3 + OpenInvAdapter1_6_R3 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.6.4-R2.0 + provided + + + + diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/AnySilentContainer.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/AnySilentContainer.java new file mode 100644 index 0000000..2f9455e --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/AnySilentContainer.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R3.AxisAlignedBB; +import net.minecraft.server.v1_6_R3.BlockEnderChest; +import net.minecraft.server.v1_6_R3.EntityOcelot; +import net.minecraft.server.v1_6_R3.EntityPlayer; +import net.minecraft.server.v1_6_R3.IInventory; +import net.minecraft.server.v1_6_R3.InventoryEnderChest; +import net.minecraft.server.v1_6_R3.InventoryLargeChest; +import net.minecraft.server.v1_6_R3.Packet100OpenWindow; +import net.minecraft.server.v1_6_R3.TileEntityChest; +import net.minecraft.server.v1_6_R3.TileEntityEnderChest; +import net.minecraft.server.v1_6_R3.World; + +import org.bukkit.craftbukkit.v1_6_R3.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + // If block next to chest is chest and has a block or ocelot on top + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = world.getTypeId(block.getX(), block.getY(), block.getZ()); + + if (world.getTypeId(block.getX(), block.getY(), block.getZ() + 1) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if (world.getTypeId(block.getX(), block.getY(), block.getZ() - 1) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (world.getTypeId(block.getX() + 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (world.getTypeId(block.getX() - 1, block.getY(), block.getZ()) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new Packet100OpenWindow(windowId, 0, ((IInventory) tile).getName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/InventoryAccess.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/InventoryAccess.java new file mode 100644 index 0000000..536887a --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R3.IInventory; + +import org.bukkit.craftbukkit.v1_6_R3.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/PlayerDataManager.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/PlayerDataManager.java new file mode 100644 index 0000000..4e38815 --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/PlayerDataManager.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_6_R3.EntityPlayer; +import net.minecraft.server.v1_6_R3.MinecraftServer; +import net.minecraft.server.v1_6_R3.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_6_R3.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + + // Create an entity to load the player data + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), offline.getName(), + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SilentContainerChest.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SilentContainerChest.java new file mode 100644 index 0000000..57675ba --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +// Volatile +import net.minecraft.server.v1_6_R3.ContainerChest; +import net.minecraft.server.v1_6_R3.EntityHuman; +import net.minecraft.server.v1_6_R3.IInventory; +import net.minecraft.server.v1_6_R3.ItemStack; +import net.minecraft.server.v1_6_R3.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.g(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried); + } + } + +} diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialEnderChest.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialEnderChest.java new file mode 100644 index 0000000..ef0a51e --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_6_R3.IInventory; +import net.minecraft.server.v1_6_R3.InventoryEnderChest; +import net.minecraft.server.v1_6_R3.InventorySubcontainer; +import net.minecraft.server.v1_6_R3.ItemStack; + +import org.bukkit.craftbukkit.v1_6_R3.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_6_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R3.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getName(), + ((CraftPlayer) p).getHandle().getEnderChest().c(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialPlayerInventory.java b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialPlayerInventory.java new file mode 100644 index 0000000..9031b60 --- /dev/null +++ b/v1_6_R3/src/main/java/com/lishid/openinv/internal/v1_6_R3/SpecialPlayerInventory.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_6_R3; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_6_R3.ItemStack; +import net.minecraft.server.v1_6_R3.PlayerInventory; + +import org.bukkit.craftbukkit.v1_6_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_6_R3.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) + return i - 27; + else + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) + return 3; + if (i == 1) + return 2; + if (i == 2) + return 1; + if (i == 3) + return 0; + else + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_7_R1/pom.xml b/v1_7_R1/pom.xml new file mode 100644 index 0000000..21f2942 --- /dev/null +++ b/v1_7_R1/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_7_R1 + OpenInvAdapter1_7_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.7.2-R0.4 + provided + + + + diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/AnySilentContainer.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/AnySilentContainer.java new file mode 100644 index 0000000..94a2046 --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/AnySilentContainer.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_7_R1.AxisAlignedBB; +import net.minecraft.server.v1_7_R1.Block; +import net.minecraft.server.v1_7_R1.BlockEnderChest; +import net.minecraft.server.v1_7_R1.EntityOcelot; +import net.minecraft.server.v1_7_R1.EntityPlayer; +import net.minecraft.server.v1_7_R1.IInventory; +import net.minecraft.server.v1_7_R1.InventoryEnderChest; +import net.minecraft.server.v1_7_R1.InventoryLargeChest; +import net.minecraft.server.v1_7_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_7_R1.TileEntityChest; +import net.minecraft.server.v1_7_R1.TileEntityEnderChest; +import net.minecraft.server.v1_7_R1.World; + +import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + // If block next to chest is chest and has a block or ocelot on top + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, 0, ((IInventory) tile).getInventoryName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/InventoryAccess.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/InventoryAccess.java new file mode 100644 index 0000000..c0f8de9 --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R1.IInventory; + +import org.bukkit.craftbukkit.v1_7_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/PlayerDataManager.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/PlayerDataManager.java new file mode 100644 index 0000000..499bc18 --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/PlayerDataManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_7_R1.EntityPlayer; +import net.minecraft.server.v1_7_R1.MinecraftServer; +import net.minecraft.server.v1_7_R1.PlayerInteractManager; +import net.minecraft.util.com.mojang.authlib.GameProfile; + +import org.bukkit.craftbukkit.v1_7_R1.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(null, offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SilentContainerChest.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SilentContainerChest.java new file mode 100644 index 0000000..232c4b7 --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +// Volatile +import net.minecraft.server.v1_7_R1.ContainerChest; +import net.minecraft.server.v1_7_R1.EntityHuman; +import net.minecraft.server.v1_7_R1.IInventory; +import net.minecraft.server.v1_7_R1.ItemStack; +import net.minecraft.server.v1_7_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.l_(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialEnderChest.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialEnderChest.java new file mode 100644 index 0000000..2d0cac5 --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_7_R1.IInventory; +import net.minecraft.server.v1_7_R1.InventoryEnderChest; +import net.minecraft.server.v1_7_R1.InventorySubcontainer; +import net.minecraft.server.v1_7_R1.ItemStack; + +import org.bukkit.craftbukkit.v1_7_R1.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getInventoryName(), + ((CraftPlayer) p).getHandle().getEnderChest().k_(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialPlayerInventory.java b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..885369a --- /dev/null +++ b/v1_7_R1/src/main/java/com/lishid/openinv/internal/v1_7_R1/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R1; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R1.ItemStack; +import net.minecraft.server.v1_7_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getInventoryName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_7_R2/pom.xml b/v1_7_R2/pom.xml new file mode 100644 index 0000000..a100986 --- /dev/null +++ b/v1_7_R2/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_7_R2 + OpenInvAdapter1_7_R2 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.7.5-R0.1 + provided + + + + diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/AnySilentContainer.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/AnySilentContainer.java new file mode 100644 index 0000000..d894316 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/AnySilentContainer.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_7_R2.AxisAlignedBB; +import net.minecraft.server.v1_7_R2.Block; +import net.minecraft.server.v1_7_R2.BlockEnderChest; +import net.minecraft.server.v1_7_R2.EntityOcelot; +import net.minecraft.server.v1_7_R2.EntityPlayer; +import net.minecraft.server.v1_7_R2.IInventory; +import net.minecraft.server.v1_7_R2.InventoryEnderChest; +import net.minecraft.server.v1_7_R2.InventoryLargeChest; +import net.minecraft.server.v1_7_R2.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_7_R2.TileEntityChest; +import net.minecraft.server.v1_7_R2.TileEntityEnderChest; +import net.minecraft.server.v1_7_R2.World; + +import org.bukkit.craftbukkit.v1_7_R2.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + // If block next to chest is chest and has a block or ocelot on top + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, 0, ((IInventory) tile).getInventoryName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/InventoryAccess.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/InventoryAccess.java new file mode 100644 index 0000000..c982a30 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R2.IInventory; + +import org.bukkit.craftbukkit.v1_7_R2.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/PlayerDataManager.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/PlayerDataManager.java new file mode 100644 index 0000000..eda1ce4 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_7_R2.EntityPlayer; +import net.minecraft.server.v1_7_R2.MinecraftServer; +import net.minecraft.server.v1_7_R2.PlayerInteractManager; +import net.minecraft.util.com.mojang.authlib.GameProfile; + +import org.bukkit.craftbukkit.v1_7_R2.CraftServer; + +@SuppressWarnings("deprecation") // Deprecated methods are used properly and will not change. +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(null, offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getName(); + } + +} diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SilentContainerChest.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SilentContainerChest.java new file mode 100644 index 0000000..7a9ce16 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +// Volatile +import net.minecraft.server.v1_7_R2.ContainerChest; +import net.minecraft.server.v1_7_R2.EntityHuman; +import net.minecraft.server.v1_7_R2.IInventory; +import net.minecraft.server.v1_7_R2.ItemStack; +import net.minecraft.server.v1_7_R2.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.l_(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialEnderChest.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialEnderChest.java new file mode 100644 index 0000000..0bd4456 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_7_R2.IInventory; +import net.minecraft.server.v1_7_R2.InventoryEnderChest; +import net.minecraft.server.v1_7_R2.InventorySubcontainer; +import net.minecraft.server.v1_7_R2.ItemStack; + +import org.bukkit.craftbukkit.v1_7_R2.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_7_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R2.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getInventoryName(), + ((CraftPlayer) p).getHandle().getEnderChest().k_(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialPlayerInventory.java b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialPlayerInventory.java new file mode 100644 index 0000000..c08d9e0 --- /dev/null +++ b/v1_7_R2/src/main/java/com/lishid/openinv/internal/v1_7_R2/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R2; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R2.ItemStack; +import net.minecraft.server.v1_7_R2.PlayerInventory; + +import org.bukkit.craftbukkit.v1_7_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R2.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getInventoryName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_7_R3/pom.xml b/v1_7_R3/pom.xml new file mode 100644 index 0000000..af3d2df --- /dev/null +++ b/v1_7_R3/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_7_R3 + OpenInvAdapter1_7_R3 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.7.9-R0.2-SNAPSHOT + provided + + + + diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/AnySilentContainer.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/AnySilentContainer.java new file mode 100644 index 0000000..173c8da --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/AnySilentContainer.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_7_R3.AxisAlignedBB; +import net.minecraft.server.v1_7_R3.Block; +import net.minecraft.server.v1_7_R3.BlockEnderChest; +import net.minecraft.server.v1_7_R3.EntityOcelot; +import net.minecraft.server.v1_7_R3.EntityPlayer; +import net.minecraft.server.v1_7_R3.IInventory; +import net.minecraft.server.v1_7_R3.InventoryEnderChest; +import net.minecraft.server.v1_7_R3.InventoryLargeChest; +import net.minecraft.server.v1_7_R3.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_7_R3.TileEntityChest; +import net.minecraft.server.v1_7_R3.TileEntityEnderChest; +import net.minecraft.server.v1_7_R3.World; + +import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + // If block next to chest is chest and has a block or ocelot on top + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = Block.b(world.getType(block.getX(), block.getY(), block.getZ())); + + if (Block.b(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if(Block.b(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (Block.b(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (Block.b(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, 0, ((IInventory) tile).getInventoryName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/InventoryAccess.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/InventoryAccess.java new file mode 100644 index 0000000..f8b23a8 --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R3.IInventory; + +import org.bukkit.craftbukkit.v1_7_R3.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/PlayerDataManager.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/PlayerDataManager.java new file mode 100644 index 0000000..7f17bc0 --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/PlayerDataManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_7_R3.EntityPlayer; +import net.minecraft.server.v1_7_R3.MinecraftServer; +import net.minecraft.server.v1_7_R3.PlayerInteractManager; +import net.minecraft.util.com.mojang.authlib.GameProfile; + +import org.bukkit.craftbukkit.v1_7_R3.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SilentContainerChest.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SilentContainerChest.java new file mode 100644 index 0000000..cc1a746 --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SilentContainerChest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +// Volatile +import net.minecraft.server.v1_7_R3.ContainerChest; +import net.minecraft.server.v1_7_R3.EntityHuman; +import net.minecraft.server.v1_7_R3.IInventory; +import net.minecraft.server.v1_7_R3.ItemStack; +import net.minecraft.server.v1_7_R3.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + i2.l_(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialEnderChest.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialEnderChest.java new file mode 100644 index 0000000..60d5e4e --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +// Volatile +import net.minecraft.server.v1_7_R3.IInventory; +import net.minecraft.server.v1_7_R3.InventoryEnderChest; +import net.minecraft.server.v1_7_R3.InventorySubcontainer; +import net.minecraft.server.v1_7_R3.ItemStack; + +import org.bukkit.craftbukkit.v1_7_R3.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R3.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private final List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getInventoryName(), + ((CraftPlayer) p).getHandle().getEnderChest().k_(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialPlayerInventory.java b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialPlayerInventory.java new file mode 100644 index 0000000..af2b6d3 --- /dev/null +++ b/v1_7_R3/src/main/java/com/lishid/openinv/internal/v1_7_R3/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R3; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R3.ItemStack; +import net.minecraft.server.v1_7_R3.PlayerInventory; + +import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R3.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getInventoryName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_7_R4/pom.xml b/v1_7_R4/pom.xml new file mode 100644 index 0000000..ae32c7e --- /dev/null +++ b/v1_7_R4/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_7_R4 + OpenInvAdapter1_7_R4 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.bukkit + craftbukkit + 1.7.10-R0.1 + provided + + + + diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/AnySilentContainer.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/AnySilentContainer.java new file mode 100644 index 0000000..cf86d73 --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/AnySilentContainer.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_7_R4.AxisAlignedBB; +import net.minecraft.server.v1_7_R4.Block; +import net.minecraft.server.v1_7_R4.BlockEnderChest; +import net.minecraft.server.v1_7_R4.EntityOcelot; +import net.minecraft.server.v1_7_R4.EntityPlayer; +import net.minecraft.server.v1_7_R4.IInventory; +import net.minecraft.server.v1_7_R4.InventoryEnderChest; +import net.minecraft.server.v1_7_R4.InventoryLargeChest; +import net.minecraft.server.v1_7_R4.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_7_R4.TileEntityChest; +import net.minecraft.server.v1_7_R4.TileEntityEnderChest; +import net.minecraft.server.v1_7_R4.World; + +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block block) { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.t(block.getX(), block.getY() + 1, block.getZ()); + } + + // If block or ocelot on top + if (isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ())) { + return true; + } + + int id = Block.getId(world.getType(block.getX(), block.getY(), block.getZ())); + + // If block next to chest is chest and has a block or ocelot on top + if (Block.getId(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() + 1); + } else if(Block.getId(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + return isBlockedChest(world, block.getX(), block.getY() + 1, block.getZ() - 1); + } else if (Block.getId(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() + 1, block.getY() + 1, block.getZ()); + } else if (Block.getId(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + return isBlockedChest(world, block.getX() - 1, block.getY() + 1, block.getZ()); + } + + return false; + } + + private boolean isBlockedChest(World world, int x, int y, int z) { + return world.t(x, y + 1, z) || hasOcelotOnTop(world, x, y, z); + } + + private boolean hasOcelotOnTop(World world, int x, int y, int z) { + for (Object localEntity : world.a(EntityOcelot.class, + AxisAlignedBB.a(x, y + 1, z, x + 1, y + 2, z + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block block) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && block.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + Object tile = world.getTileEntity(block.getX(), block.getY(), block.getZ()); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + int id = Block.getId(world.getType(block.getX(), block.getY(), block.getZ())); + + if (Block.getId(world.getType(block.getX(), block.getY(), block.getZ() + 1)) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() + 1)); + } else if(Block.getId(world.getType(block.getX(), block.getY(), block.getZ() - 1)) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX(), block.getY(), block.getZ() - 1), (IInventory) tile); + } else if (Block.getId(world.getType(block.getX() + 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (IInventory) tile, (TileEntityChest) world.getTileEntity(block.getX() + 1, block.getY(), block.getZ())); + } else if (Block.getId(world.getType(block.getX() - 1, block.getY(), block.getZ())) == id) { + tile = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(block.getX() - 1, block.getY(), block.getZ()), (IInventory) tile); + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + int windowId = 0; + try { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + windowId = windowID.getInt(player); + windowId = windowId % 100 + 1; + windowID.setInt(player, windowId); + } catch (NoSuchFieldException e) {} + + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, 0, ((IInventory) tile).getInventoryName(), ((IInventory) tile).getSize(), true)); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) tile)); + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/InventoryAccess.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/InventoryAccess.java new file mode 100644 index 0000000..b41fd40 --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R4.IInventory; + +import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/PlayerDataManager.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/PlayerDataManager.java new file mode 100644 index 0000000..b26947d --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/PlayerDataManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_7_R4.EntityPlayer; +import net.minecraft.server.v1_7_R4.MinecraftServer; +import net.minecraft.server.v1_7_R4.PlayerInteractManager; +import net.minecraft.util.com.mojang.authlib.GameProfile; + +import org.bukkit.craftbukkit.v1_7_R4.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SilentContainerChest.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SilentContainerChest.java new file mode 100644 index 0000000..b816cee --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +// Volatile +import net.minecraft.server.v1_7_R4.ContainerChest; +import net.minecraft.server.v1_7_R4.EntityHuman; +import net.minecraft.server.v1_7_R4.IInventory; +import net.minecraft.server.v1_7_R4.ItemStack; +import net.minecraft.server.v1_7_R4.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2) { + super(i1, i2); + // Send close signal + i2.closeContainer(); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialEnderChest.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialEnderChest.java new file mode 100644 index 0000000..3ff6db5 --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialEnderChest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +//Volatile +import net.minecraft.server.v1_7_R4.IInventory; +import net.minecraft.server.v1_7_R4.InventoryEnderChest; +import net.minecraft.server.v1_7_R4.InventorySubcontainer; +import net.minecraft.server.v1_7_R4.ItemStack; + +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + public List transaction = new ArrayList(); + private boolean playerOnline = false; + private CraftPlayer owner; + private int maxStack = MAX_STACK; + + public SpecialEnderChest(Player p, Boolean online) { + super(((CraftPlayer) p).getHandle().getEnderChest().getInventoryName(), + ((CraftPlayer) p).getHandle().getEnderChest().k_(), + ((CraftPlayer) p).getHandle().getEnderChest().getSize()); + CraftPlayer player = (CraftPlayer) p; + this.enderChest = player.getHandle().getEnderChest(); + this.owner = player; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + owner = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = owner.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + return this.items; + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialPlayerInventory.java b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialPlayerInventory.java new file mode 100644 index 0000000..1283d4e --- /dev/null +++ b/v1_7_R4/src/main/java/com/lishid/openinv/internal/v1_7_R4/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_7_R4; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_7_R4.ItemStack; +import net.minecraft.server.v1_7_R4.PlayerInventory; + +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getInventoryName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_8_R1/pom.xml b/v1_8_R1/pom.xml new file mode 100644 index 0000000..8864486 --- /dev/null +++ b/v1_8_R1/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_8_R1 + OpenInvAdapter1_8_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.8-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java new file mode 100644 index 0000000..6968d2d --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_8_R1.AxisAlignedBB; +import net.minecraft.server.v1_8_R1.Block; +import net.minecraft.server.v1_8_R1.BlockChest; +import net.minecraft.server.v1_8_R1.BlockEnderChest; +import net.minecraft.server.v1_8_R1.BlockPosition; +import net.minecraft.server.v1_8_R1.EntityOcelot; +import net.minecraft.server.v1_8_R1.EntityPlayer; +import net.minecraft.server.v1_8_R1.EnumDirection; +import net.minecraft.server.v1_8_R1.IInventory; +import net.minecraft.server.v1_8_R1.ITileInventory; +import net.minecraft.server.v1_8_R1.InventoryEnderChest; +import net.minecraft.server.v1_8_R1.InventoryLargeChest; +import net.minecraft.server.v1_8_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R1.TileEntity; +import net.minecraft.server.v1_8_R1.TileEntityChest; +import net.minecraft.server.v1_8_R1.TileEntityEnderChest; +import net.minecraft.server.v1_8_R1.World; + +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).getBlock().c(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.values()) { + if (!localEnumDirection.k().c()) { + // Not horizontal + continue; + } + + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).getBlock().c() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Object localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.values()) { + if (!localEnumDirection.k().c()) { + // Not horizontal + continue; + } + + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/InventoryAccess.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/InventoryAccess.java new file mode 100644 index 0000000..20e6d09 --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R1.IInventory; + +import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/PlayerDataManager.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/PlayerDataManager.java new file mode 100644 index 0000000..1b45d27 --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import net.minecraft.server.v1_8_R1.EntityPlayer; +import net.minecraft.server.v1_8_R1.MinecraftServer; +import net.minecraft.server.v1_8_R1.PlayerInteractManager; + +//Volatile +import org.bukkit.craftbukkit.v1_8_R1.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java new file mode 100644 index 0000000..5a5a8af --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +//Volatile +import net.minecraft.server.v1_8_R1.ContainerChest; +import net.minecraft.server.v1_8_R1.EntityHuman; +import net.minecraft.server.v1_8_R1.IInventory; +import net.minecraft.server.v1_8_R1.ItemStack; +import net.minecraft.server.v1_8_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // Send close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialEnderChest.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialEnderChest.java new file mode 100644 index 0000000..9c2283f --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialEnderChest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +//Volatile +import net.minecraft.server.v1_8_R1.IInventory; +import net.minecraft.server.v1_8_R1.InventoryEnderChest; +import net.minecraft.server.v1_8_R1.InventorySubcontainer; + +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = craftPlayer.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialPlayerInventory.java b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..0ba51a6 --- /dev/null +++ b/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R1; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +//Volatile +import net.minecraft.server.v1_8_R1.ItemStack; +import net.minecraft.server.v1_8_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_8_R2/pom.xml b/v1_8_R2/pom.xml new file mode 100644 index 0000000..a002526 --- /dev/null +++ b/v1_8_R2/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_8_R2 + OpenInvAdapter1_8_R2 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.8.3-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java new file mode 100644 index 0000000..ebf2042 --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_8_R2.AxisAlignedBB; +import net.minecraft.server.v1_8_R2.Block; +import net.minecraft.server.v1_8_R2.BlockChest; +import net.minecraft.server.v1_8_R2.BlockEnderChest; +import net.minecraft.server.v1_8_R2.BlockPosition; +import net.minecraft.server.v1_8_R2.Entity; +import net.minecraft.server.v1_8_R2.EntityOcelot; +import net.minecraft.server.v1_8_R2.EntityPlayer; +import net.minecraft.server.v1_8_R2.EnumDirection; +import net.minecraft.server.v1_8_R2.IInventory; +import net.minecraft.server.v1_8_R2.ITileInventory; +import net.minecraft.server.v1_8_R2.InventoryEnderChest; +import net.minecraft.server.v1_8_R2.InventoryLargeChest; +import net.minecraft.server.v1_8_R2.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R2.StatisticList; +import net.minecraft.server.v1_8_R2.TileEntity; +import net.minecraft.server.v1_8_R2.TileEntityChest; +import net.minecraft.server.v1_8_R2.TileEntityEnderChest; +import net.minecraft.server.v1_8_R2.World; + +import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).getBlock().c(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).getBlock().c() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.V); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.V); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + + if (((BlockChest) block).b == 0) + player.b(StatisticList.aa); + else if (((BlockChest) block).b == 1) { + player.b(StatisticList.U); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/InventoryAccess.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/InventoryAccess.java new file mode 100644 index 0000000..6d3e6ff --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R2.IInventory; + +import org.bukkit.craftbukkit.v1_8_R2.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/PlayerDataManager.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/PlayerDataManager.java new file mode 100644 index 0000000..d79bb09 --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_8_R2.EntityPlayer; +import net.minecraft.server.v1_8_R2.MinecraftServer; +import net.minecraft.server.v1_8_R2.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_8_R2.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java new file mode 100644 index 0000000..d7e1196 --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +// Volatile +import net.minecraft.server.v1_8_R2.ContainerChest; +import net.minecraft.server.v1_8_R2.EntityHuman; +import net.minecraft.server.v1_8_R2.IInventory; +import net.minecraft.server.v1_8_R2.ItemStack; +import net.minecraft.server.v1_8_R2.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // Send close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialEnderChest.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialEnderChest.java new file mode 100644 index 0000000..e353cd9 --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialEnderChest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R2.IInventory; +import net.minecraft.server.v1_8_R2.InventoryEnderChest; +import net.minecraft.server.v1_8_R2.InventorySubcontainer; + +import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R2.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = craftPlayer.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialPlayerInventory.java b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialPlayerInventory.java new file mode 100644 index 0000000..34bd8ab --- /dev/null +++ b/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R2; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R2.ItemStack; +import net.minecraft.server.v1_8_R2.PlayerInventory; + +import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R2.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].a(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_8_R3/pom.xml b/v1_8_R3/pom.xml new file mode 100644 index 0000000..972b9ae --- /dev/null +++ b/v1_8_R3/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_8_R3 + OpenInvAdapter1_8_R3 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.8.8-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java new file mode 100644 index 0000000..ec13927 --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +//Volatile +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.Block; +import net.minecraft.server.v1_8_R3.BlockChest; +import net.minecraft.server.v1_8_R3.BlockEnderChest; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityOcelot; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.EnumDirection; +import net.minecraft.server.v1_8_R3.IInventory; +import net.minecraft.server.v1_8_R3.ITileInventory; +import net.minecraft.server.v1_8_R3.InventoryEnderChest; +import net.minecraft.server.v1_8_R3.InventoryLargeChest; +import net.minecraft.server.v1_8_R3.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R3.StatisticList; +import net.minecraft.server.v1_8_R3.TileEntity; +import net.minecraft.server.v1_8_R3.TileEntityChest; +import net.minecraft.server.v1_8_R3.TileEntityEnderChest; +import net.minecraft.server.v1_8_R3.World; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).getBlock().c(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).getBlock().c() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.V); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.V); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + + if (((BlockChest) block).b == 0) + player.b(StatisticList.aa); + else if (((BlockChest) block).b == 1) { + player.b(StatisticList.U); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/InventoryAccess.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/InventoryAccess.java new file mode 100644 index 0000000..82d9d3e --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R3.IInventory; + +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java new file mode 100644 index 0000000..818e703 --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.MinecraftServer; +import net.minecraft.server.v1_8_R3.PlayerInteractManager; + +//Volatile +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java new file mode 100644 index 0000000..24c4288 --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +// Volatile +import net.minecraft.server.v1_8_R3.ContainerChest; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.IInventory; +import net.minecraft.server.v1_8_R3.ItemStack; +import net.minecraft.server.v1_8_R3.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java new file mode 100644 index 0000000..a8780c5 --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_8_R3.IInventory; +import net.minecraft.server.v1_8_R3.InventoryEnderChest; +import net.minecraft.server.v1_8_R3.InventorySubcontainer; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = craftPlayer.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java new file mode 100644 index 0000000..25d0536 --- /dev/null +++ b/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_8_R3; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +//Volatile +import net.minecraft.server.v1_8_R3.ItemStack; +import net.minecraft.server.v1_8_R3.PlayerInventory; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[5]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + this.items = player.inventory.items; + this.armor = player.inventory.armor; + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + this.player.inventory.items = this.items; + this.player.inventory.armor = this.armor; + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 5; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].cloneAndSubtract(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_9_R1/pom.xml b/v1_9_R1/pom.xml new file mode 100644 index 0000000..07e89da --- /dev/null +++ b/v1_9_R1/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_9_R1 + OpenInvAdapter1_9_R1 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.9-R0.1-SNAPSHOT + provided + + + diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java new file mode 100644 index 0000000..eaf4f2f --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_9_R1.AxisAlignedBB; +import net.minecraft.server.v1_9_R1.Block; +import net.minecraft.server.v1_9_R1.BlockChest; +import net.minecraft.server.v1_9_R1.BlockEnderChest; +import net.minecraft.server.v1_9_R1.BlockPosition; +import net.minecraft.server.v1_9_R1.Entity; +import net.minecraft.server.v1_9_R1.EntityOcelot; +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.EnumDirection; +import net.minecraft.server.v1_9_R1.IInventory; +import net.minecraft.server.v1_9_R1.ITileInventory; +import net.minecraft.server.v1_9_R1.InventoryEnderChest; +import net.minecraft.server.v1_9_R1.InventoryLargeChest; +import net.minecraft.server.v1_9_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_9_R1.StatisticList; +import net.minecraft.server.v1_9_R1.TileEntity; +import net.minecraft.server.v1_9_R1.TileEntityChest; +import net.minecraft.server.v1_9_R1.TileEntityEnderChest; +import net.minecraft.server.v1_9_R1.World; + +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).m(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).l() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.X); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.X); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + + if (((BlockChest) block).g == BlockChest.Type.BASIC) + player.b(StatisticList.ac); + else if (((BlockChest) block).g == BlockChest.Type.TRAP) { + player.b(StatisticList.W); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/InventoryAccess.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/InventoryAccess.java new file mode 100644 index 0000000..c9d48f8 --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R1.IInventory; + +import org.bukkit.craftbukkit.v1_9_R1.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/PlayerDataManager.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/PlayerDataManager.java new file mode 100644 index 0000000..0166f62 --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_9_R1.EntityPlayer; +import net.minecraft.server.v1_9_R1.MinecraftServer; +import net.minecraft.server.v1_9_R1.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_9_R1.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure the player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java new file mode 100644 index 0000000..3a25cf6 --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +// Volatile +import net.minecraft.server.v1_9_R1.ContainerChest; +import net.minecraft.server.v1_9_R1.EntityHuman; +import net.minecraft.server.v1_9_R1.IInventory; +import net.minecraft.server.v1_9_R1.ItemStack; +import net.minecraft.server.v1_9_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // Send close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialEnderChest.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialEnderChest.java new file mode 100644 index 0000000..2306fca --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialEnderChest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R1.IInventory; +import net.minecraft.server.v1_9_R1.InventoryEnderChest; +import net.minecraft.server.v1_9_R1.InventorySubcontainer; + +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_9_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = craftPlayer.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialPlayerInventory.java b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialPlayerInventory.java new file mode 100644 index 0000000..1b61828 --- /dev/null +++ b/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SpecialPlayerInventory.java @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R1; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R1.ItemStack; +import net.minecraft.server.v1_9_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_9_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[4]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + setItemArrays(this, player.inventory.items, player.inventory.armor, player.inventory.extraSlots); + } + + private void setItemArrays(PlayerInventory inventory, ItemStack[] items, ItemStack[] armor, + ItemStack[] extraSlots) { + try { + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + + // Access and replace main inventory array + Field field = PlayerInventory.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, items); + + // Access and replace armor inventory array + field = PlayerInventory.class.getField("armor"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, armor); + + // Access and replace offhand inventory array + field = PlayerInventory.class.getField("extraSlots"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, extraSlots); + + // Access and replace array containing all inventory arrays + field = PlayerInventory.class.getDeclaredField("g"); + field.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, new ItemStack[][] { items, armor, extraSlots }); + } catch (NoSuchFieldException e) { + // Unable to set final fields to item arrays, we're screwed. Noisily fail. + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + setItemArrays(this.player.inventory, items, armor, extraSlots); + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + System.arraycopy(extraSlots, 0, contents, items.length + armor.length, extraSlots.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 4; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // extraSlots is, for now, just an array with length 1. No need for special handling. + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].cloneAndSubtract(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +} diff --git a/v1_9_R2/pom.xml b/v1_9_R2/pom.xml new file mode 100644 index 0000000..d4693b7 --- /dev/null +++ b/v1_9_R2/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.lishid + openinv + 1.0-SNAPSHOT + + + openinvadapter1_9_R2 + OpenInvaAdapter1_9_R2 + + + + com.lishid + openinvplugin + 1.0-SNAPSHOT + + + org.spigotmc + spigot + 1.9.4-R0.1-SNAPSHOT + provided + + + + diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java new file mode 100644 index 0000000..5adea2e --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +import com.lishid.openinv.internal.IAnySilentContainer; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_9_R2.AxisAlignedBB; +import net.minecraft.server.v1_9_R2.Block; +import net.minecraft.server.v1_9_R2.BlockChest; +import net.minecraft.server.v1_9_R2.BlockEnderChest; +import net.minecraft.server.v1_9_R2.BlockPosition; +import net.minecraft.server.v1_9_R2.Entity; +import net.minecraft.server.v1_9_R2.EntityOcelot; +import net.minecraft.server.v1_9_R2.EntityPlayer; +import net.minecraft.server.v1_9_R2.EnumDirection; +import net.minecraft.server.v1_9_R2.IInventory; +import net.minecraft.server.v1_9_R2.ITileInventory; +import net.minecraft.server.v1_9_R2.InventoryEnderChest; +import net.minecraft.server.v1_9_R2.InventoryLargeChest; +import net.minecraft.server.v1_9_R2.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_9_R2.StatisticList; +import net.minecraft.server.v1_9_R2.TileEntity; +import net.minecraft.server.v1_9_R2.TileEntityChest; +import net.minecraft.server.v1_9_R2.TileEntityEnderChest; +import net.minecraft.server.v1_9_R2.World; + +import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(org.bukkit.block.Block block) { + return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; + } + + @Override + public boolean isAnyContainerNeeded(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).m(); + } + + // Check if chest is blocked or has an ocelot on top + if (isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedChest(World world, BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).l() || hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + + @Override + public boolean activateContainer(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.X); + return true; + } + + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.X); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockChest) { + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (silentchest) { + tile = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + + if (((BlockChest) block).g == BlockChest.Type.BASIC) + player.b(StatisticList.ac); + else if (((BlockChest) block).g == BlockChest.Type.TRAP) { + player.b(StatisticList.W); + } + } + + boolean returnValue = false; + if (!silentchest) { + player.openContainer((IInventory) tile); + returnValue = true; + } else { + try { + SilentContainerChest silentContainerChest = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + int windowId = player.nextContainerCounter(); + player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); + player.activeContainer = silentContainerChest; + player.activeContainer.windowId = windowId; + player.activeContainer.addSlotListener(player); + returnValue = true; + } catch (Exception e) { + e.printStackTrace(); + p.sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + return returnValue; + } + +} diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/InventoryAccess.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/InventoryAccess.java new file mode 100644 index 0000000..0f09b1c --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/InventoryAccess.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; + +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R2.IInventory; + +import org.bukkit.craftbukkit.v1_9_R2.inventory.CraftInventory; + +public class InventoryAccess implements IInventoryAccess { + + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; + } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + +} diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/PlayerDataManager.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/PlayerDataManager.java new file mode 100644 index 0000000..3678093 --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/PlayerDataManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +// Volatile +import net.minecraft.server.v1_9_R2.EntityPlayer; +import net.minecraft.server.v1_9_R2.MinecraftServer; +import net.minecraft.server.v1_9_R2.PlayerInteractManager; + +import org.bukkit.craftbukkit.v1_9_R2.CraftServer; + +public class PlayerDataManager implements IPlayerDataManager { + + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; + } + + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; + } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + +} diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java new file mode 100644 index 0000000..d0fba74 --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +// Volatile +import net.minecraft.server.v1_9_R2.ContainerChest; +import net.minecraft.server.v1_9_R2.EntityHuman; +import net.minecraft.server.v1_9_R2.IInventory; +import net.minecraft.server.v1_9_R2.ItemStack; +import net.minecraft.server.v1_9_R2.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { + super(i1, i2, e1); + // Send close signal + i2.closeContainer(e1); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != null) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(null); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialEnderChest.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialEnderChest.java new file mode 100644 index 0000000..01c4be5 --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialEnderChest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +import java.lang.reflect.Field; + +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R2.IInventory; +import net.minecraft.server.v1_9_R2.InventoryEnderChest; +import net.minecraft.server.v1_9_R2.InventorySubcontainer; + +import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_9_R2.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { + + private final InventoryEnderChest enderChest; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + this.items = enderChest.getContents(); + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + InventoryEnderChest playerEnderChest = craftPlayer.getHandle().getEnderChest(); + Field field = playerEnderChest.getClass().getField("items"); + field.setAccessible(true); + field.set(playerEnderChest, this.items); + } catch (Exception e) {} + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void update() { + super.update(); + enderChest.update(); + } + +} diff --git a/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialPlayerInventory.java b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialPlayerInventory.java new file mode 100644 index 0000000..4682171 --- /dev/null +++ b/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SpecialPlayerInventory.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lishid.openinv.internal.v1_9_R2; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +// Volatile +import net.minecraft.server.v1_9_R2.ItemStack; +import net.minecraft.server.v1_9_R2.PlayerInventory; + +import org.bukkit.craftbukkit.v1_9_R2.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_9_R2.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { + + private final ItemStack[] extra = new ItemStack[4]; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; + + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); + this.playerOnline = online; + setItemArrays(this, player.inventory.items, player.inventory.armor, player.inventory.extraSlots); + } + + private void setItemArrays(PlayerInventory inventory, ItemStack[] items, ItemStack[] armor, + ItemStack[] extraSlots) { + try { + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + + // Access and replace main inventory array + Field field = PlayerInventory.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, items); + + // Access and replace armor inventory array + field = PlayerInventory.class.getField("armor"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, armor); + + // Access and replace offhand inventory array + field = PlayerInventory.class.getField("extraSlots"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, extraSlots); + + // Access and replace array containing all inventory arrays + field = PlayerInventory.class.getDeclaredField("g"); + field.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, new ItemStack[][] { items, armor, extraSlots }); + } catch (NoSuchFieldException e) { + // Unable to set final fields to item arrays, we're screwed. Noisily fail. + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public Inventory getBukkitInventory() { + return inventory; + } + + @Override + public void setPlayerOnline(Player player) { + if (!playerOnline) { + this.player = ((CraftPlayer) player).getHandle(); + setItemArrays(this.player.inventory, items, armor, extraSlots); + playerOnline = true; + } + } + + @Override + public void setPlayerOffline() { + playerOnline = false; + } + + @Override + public boolean isInUse() { + return !this.getViewers().isEmpty(); + } + + @Override + public void onClose(CraftHumanEntity who) { + super.onClose(who); + } + + @Override + public ItemStack[] getContents() { + ItemStack[] contents = new ItemStack[getSize()]; + System.arraycopy(items, 0, contents, 0, items.length); + System.arraycopy(armor, 0, contents, items.length, armor.length); + System.arraycopy(extraSlots, 0, contents, items.length + armor.length, extraSlots.length); + return contents; + } + + @Override + public int getSize() { + return super.getSize() + 4; + } + + @Override + public ItemStack getItem(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // extraSlots is, for now, just an array with length 1. No need for special handling. + return is[i]; + } + + @Override + public ItemStack splitStack(int i, int j) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack; + + if (is[i].count <= j) { + itemstack = is[i]; + is[i] = null; + return itemstack; + } else { + itemstack = is[i].cloneAndSubtract(j); + if (is[i].count == 0) { + is[i] = null; + } + + return itemstack; + } + } + + return null; + } + + @Override + public ItemStack splitWithoutUpdate(int i) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + if (is[i] != null) { + ItemStack itemstack = is[i]; + + is[i] = null; + return itemstack; + } + + return null; + } + + @Override + public void setItem(int i, ItemStack itemstack) { + ItemStack[] is = this.items; + + if (i >= is.length) { + i -= is.length; + is = this.armor; + } else { + i = getReversedItemSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extraSlots; + } else if (is == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= is.length) { + i -= is.length; + is = this.extra; + } + + // Effects + if (is == this.extra) { + player.drop(itemstack, true); + itemstack = null; + } + + is[i] = itemstack; + + player.defaultContainer.b(); + } + + private int getReversedItemSlotNum(int i) { + if (i >= 27) { + return i - 27; + } + return i + 9; + } + + private int getReversedArmorSlotNum(int i) { + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + + return i; + } + + @Override + public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } + return player.getName(); + } + +}