From 1bd7932cc51857731b2ce0c9098388f40278c9ec Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 16 Mar 2021 09:34:41 -0400 Subject: [PATCH 1/8] Drop 1.8/1.15/1.16.3 support (#185) With the recent uptick in requests for support by people running 1.12 who have recently updated past Java 9, I revisited the supported versions. First, the "modern" versions: 1.15 is run by 2.9% of servers, 1.16.3 by 5%. Since all of these versions are supported to ease the transition of updating servers and servers have updated, there's no real reason to keep them around. It's a lot easier if you can update a plugin and just have it work on both versions rather than push all the plugin updates to master with the server update, but none of these versions have any reason for long-term support. Regarding heavily outdated server software: As of the time of writing, 1.8 and 1.12 have market shares of 8.6% and 8.5% of servers respectively. Regarding 1.8: 1.8 support is already a bit wonky - with the changes made to inventory names, it's not (easily) possible to bridge the gap, and future changes will make that more and more difficult. People use 1.8 because they disliked the 1.9 combat changes, but there are plugins that fully rework combat to how it used to be. I have yet to hear a compelling argument that cannot be resolved with plugins. In the interest of my own sanity (handling and backporting the inventory name change in particular was a real humdinger) I will no longer be backporting changes to 1.8. Regarding 1.12: I am honestly not sure why people are not updating. I get it, 1.13 and the flattening was a rough transition, but pretty much every developer active at the time bridged the gap. If your server is heavily dependent on some software only available at that time, you can live with other software available at that time. At the time of 1.12's release, Java 9 was not released. Either update your server, downgrade Java, or fork OpenInv and backport Java 9 support yourself. --- .github/workflows/ci.yml | 3 - api/pom.xml | 2 +- internal/pom.xml | 3 - internal/v1_15_R1/pom.xml | 75 -- .../internal/v1_15_R1/AnySilentContainer.java | 359 --------- .../internal/v1_15_R1/PlayerDataManager.java | 289 ------- .../internal/v1_15_R1/SpecialEnderChest.java | 256 ------ .../v1_15_R1/SpecialPlayerInventory.java | 757 ------------------ internal/v1_16_R2/pom.xml | 75 -- .../internal/v1_16_R2/AnySilentContainer.java | 358 --------- .../internal/v1_16_R2/PlayerDataManager.java | 295 ------- .../internal/v1_16_R2/SpecialEnderChest.java | 256 ------ .../v1_16_R2/SpecialPlayerInventory.java | 733 ----------------- internal/v1_8_R3/pom.xml | 74 -- .../internal/v1_8_R3/AnySilentContainer.java | 250 ------ .../internal/v1_8_R3/PlayerDataManager.java | 201 ----- .../internal/v1_8_R3/SpecialEnderChest.java | 83 -- .../v1_8_R3/SpecialPlayerInventory.java | 230 ------ .../lishid/openinv/util/InternalAccessor.java | 1 + plugin/src/main/resources/plugin.yml | 2 +- 20 files changed, 3 insertions(+), 4299 deletions(-) delete mode 100644 internal/v1_15_R1/pom.xml delete mode 100644 internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/AnySilentContainer.java delete mode 100644 internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/PlayerDataManager.java delete mode 100644 internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialEnderChest.java delete mode 100644 internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialPlayerInventory.java delete mode 100644 internal/v1_16_R2/pom.xml delete mode 100644 internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/AnySilentContainer.java delete mode 100644 internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/PlayerDataManager.java delete mode 100644 internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialEnderChest.java delete mode 100644 internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialPlayerInventory.java delete mode 100644 internal/v1_8_R3/pom.xml delete mode 100644 internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java delete mode 100644 internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java delete mode 100644 internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java delete mode 100644 internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6489274..932d513 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,9 +36,6 @@ jobs: mkdir ~/buildtools cd ~/buildtools wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar - java -jar BuildTools.jar --rev 1.8.8 - java -jar BuildTools.jar --rev 1.15.2 - java -jar BuildTools.jar --rev 1.16.3 java -jar BuildTools.jar --rev 1.16.4 - name: Build With Maven diff --git a/api/pom.xml b/api/pom.xml index e419bf2..cc34012 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -36,7 +36,7 @@ org.spigotmc spigot-api - 1.8.8-R0.1-SNAPSHOT + 1.16.5-R0.1-SNAPSHOT provided diff --git a/internal/pom.xml b/internal/pom.xml index e7dc5b0..fd28dce 100644 --- a/internal/pom.xml +++ b/internal/pom.xml @@ -33,9 +33,6 @@ all - v1_8_R3 - v1_15_R1 - v1_16_R2 v1_16_R3 diff --git a/internal/v1_15_R1/pom.xml b/internal/v1_15_R1/pom.xml deleted file mode 100644 index 2000c76..0000000 --- a/internal/v1_15_R1/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.6-SNAPSHOT - - - openinvadapter1_15_R1 - OpenInvAdapter1_15_R1 - - - - org.spigotmc - spigot - 1.15.2-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.6-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.2 - - true - - - - package - - shade - - - - - - - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - - \ No newline at end of file diff --git a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/AnySilentContainer.java b/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/AnySilentContainer.java deleted file mode 100644 index 3cceef7..0000000 --- a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/AnySilentContainer.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_15_R1; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.internal.IAnySilentContainer; -import java.lang.reflect.Field; -import net.minecraft.server.v1_15_R1.Block; -import net.minecraft.server.v1_15_R1.BlockBarrel; -import net.minecraft.server.v1_15_R1.BlockChest; -import net.minecraft.server.v1_15_R1.BlockChestTrapped; -import net.minecraft.server.v1_15_R1.BlockEnderChest; -import net.minecraft.server.v1_15_R1.BlockPosition; -import net.minecraft.server.v1_15_R1.BlockPropertyChestType; -import net.minecraft.server.v1_15_R1.BlockShulkerBox; -import net.minecraft.server.v1_15_R1.ChatMessage; -import net.minecraft.server.v1_15_R1.Container; -import net.minecraft.server.v1_15_R1.ContainerChest; -import net.minecraft.server.v1_15_R1.Containers; -import net.minecraft.server.v1_15_R1.EntityHuman; -import net.minecraft.server.v1_15_R1.EntityPlayer; -import net.minecraft.server.v1_15_R1.EnumGamemode; -import net.minecraft.server.v1_15_R1.IBlockData; -import net.minecraft.server.v1_15_R1.IChatBaseComponent; -import net.minecraft.server.v1_15_R1.ITileInventory; -import net.minecraft.server.v1_15_R1.InventoryEnderChest; -import net.minecraft.server.v1_15_R1.InventoryLargeChest; -import net.minecraft.server.v1_15_R1.PlayerInteractManager; -import net.minecraft.server.v1_15_R1.PlayerInventory; -import net.minecraft.server.v1_15_R1.TileEntity; -import net.minecraft.server.v1_15_R1.TileEntityChest; -import net.minecraft.server.v1_15_R1.TileEntityEnderChest; -import net.minecraft.server.v1_15_R1.TileEntityLootable; -import net.minecraft.server.v1_15_R1.TileInventory; -import net.minecraft.server.v1_15_R1.World; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.block.Barrel; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.EnderChest; -import org.bukkit.block.ShulkerBox; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.type.Chest; -import org.bukkit.entity.Cat; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryView; -import org.bukkit.util.BoundingBox; -import org.jetbrains.annotations.NotNull; - -public class AnySilentContainer implements IAnySilentContainer { - - private Field playerInteractManagerGamemode; - - public AnySilentContainer() { - try { - this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); - this.playerInteractManagerGamemode.setAccessible(true); - } catch (NoSuchFieldException | SecurityException e) { - System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); - e.printStackTrace(); - } - } - - @Override - public boolean isAnySilentContainer(@NotNull final org.bukkit.block.Block bukkitBlock) { - if (bukkitBlock.getType() == Material.ENDER_CHEST) { - return true; - } - BlockState state = bukkitBlock.getState(); - return state instanceof org.bukkit.block.Chest - || state instanceof org.bukkit.block.ShulkerBox - || state instanceof org.bukkit.block.Barrel; - } - - @Override - public boolean isAnyContainerNeeded(@NotNull final Player p, @NotNull final org.bukkit.block.Block block) { - BlockState blockState = block.getState(); - - // Barrels do not require AnyContainer. - if (blockState instanceof Barrel) { - return false; - } - - // Enderchests require a non-occluding block on top to open. - if (blockState instanceof EnderChest) { - return block.getRelative(0, 1, 0).getType().isOccluding(); - } - - // Shulker boxes require 1/2 a block clear in the direction they open. - if (blockState instanceof ShulkerBox) { - BoundingBox boundingBox = block.getBoundingBox(); - if (boundingBox.getVolume() > 1) { - // Shulker box is already open. - return false; - } - - BlockData blockData = block.getBlockData(); - if (!(blockData instanceof Directional)) { - // Shouldn't be possible. Just in case, demand AnyChest. - return true; - } - - Directional directional = (Directional) blockData; - BlockFace face = directional.getFacing(); - boundingBox.shift(face.getDirection()); - // Return whether or not bounding boxes overlap. - return block.getRelative(face, 1).getBoundingBox().overlaps(boundingBox); - } - - if (!(blockState instanceof org.bukkit.block.Chest)) { - return false; - } - - if (isBlockedChest(block)) { - return true; - } - - BlockData blockData = block.getBlockData(); - if (!(blockData instanceof Chest) || ((Chest) blockData).getType() == Chest.Type.SINGLE) { - return false; - } - - Chest chest = (Chest) blockData; - int ordinal = (chest.getFacing().ordinal() + 4 + (chest.getType() == Chest.Type.RIGHT ? -1 : 1)) % 4; - BlockFace relativeFace = BlockFace.values()[ordinal]; - org.bukkit.block.Block relative = block.getRelative(relativeFace); - - if (relative.getType() != block.getType()) { - return false; - } - - BlockData relativeData = relative.getBlockData(); - if (!(relativeData instanceof Chest)) { - return false; - } - - Chest relativeChest = (Chest) relativeData; - if (relativeChest.getFacing() != chest.getFacing() - || relativeChest.getType() != (chest.getType() == Chest.Type.RIGHT ? Chest.Type.LEFT : Chest.Type.RIGHT)) { - return false; - } - - return isBlockedChest(relative); - } - - private boolean isBlockedChest(org.bukkit.block.Block block) { - org.bukkit.block.Block relative = block.getRelative(0, 1, 0); - return relative.getType().isOccluding() - || block.getWorld().getNearbyEntities(BoundingBox.of(relative), entity -> entity instanceof Cat).size() > 0; - } - - @Override - public boolean activateContainer(@NotNull final Player bukkitPlayer, final boolean silentchest, - @NotNull final org.bukkit.block.Block bukkitBlock) { - - // Silent ender chest is API-only - if (silentchest && bukkitBlock.getType() == Material.ENDER_CHEST) { - bukkitPlayer.openInventory(bukkitPlayer.getEnderChest()); - bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED); - return true; - } - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - final World world = player.world; - final BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ()); - final TileEntity 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(new TileInventory((containerCounter, playerInventory, ignored) -> { - Containers containers; - int rows = enderChest.getSize() / 9; - switch (rows) { - case 1: - containers = Containers.GENERIC_9X1; - break; - case 2: - containers = Containers.GENERIC_9X2; - break; - case 3: - default: - containers = Containers.GENERIC_9X3; - break; - case 4: - containers = Containers.GENERIC_9X4; - break; - case 5: - containers = Containers.GENERIC_9X5; - break; - case 6: - containers = Containers.GENERIC_9X6; - break; - } - return new ContainerChest(containers, containerCounter, playerInventory, enderChest, rows); - }, BlockEnderChest.e)); - bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED); - return true; - } - - if (!(tile instanceof ITileInventory)) { - return false; - } - - ITileInventory tileInventory = (ITileInventory) tile; - IBlockData blockData = world.getType(blockPosition); - Block block = blockData.getBlock(); - - if (block instanceof BlockChest) { - - BlockPropertyChestType chestType = blockData.get(BlockChest.c); - - if (chestType != BlockPropertyChestType.SINGLE) { - - BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.i(blockData)); - IBlockData adjacentBlockData = world.getType(adjacentBlockPosition); - - if (adjacentBlockData.getBlock() == block) { - - BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.c); - - if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType - && adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) { - - TileEntity adjacentTile = world.getTileEntity(adjacentBlockPosition); - - if (adjacentTile instanceof TileEntityChest && tileInventory instanceof TileEntityChest) { - TileEntityChest rightChest = chestType == BlockPropertyChestType.RIGHT ? ((TileEntityChest) tileInventory) : (TileEntityChest) adjacentTile; - TileEntityChest leftChest = chestType == BlockPropertyChestType.RIGHT ? (TileEntityChest) adjacentTile : ((TileEntityChest) tileInventory); - - if (silentchest && (rightChest.lootTable != null || leftChest.lootTable != null)) { - OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated"); - return false; - } - - tileInventory = new ITileInventory() { - public Container createMenu(int containerCounter, PlayerInventory playerInventory, EntityHuman entityHuman) { - leftChest.d(playerInventory.player); - rightChest.d(playerInventory.player); - return ContainerChest.b(containerCounter, playerInventory, new InventoryLargeChest(rightChest, leftChest)); - } - - public IChatBaseComponent getScoreboardDisplayName() { - return new ChatMessage("container.chestDouble"); - } - }; - } - } - } - } - - if (block instanceof BlockChestTrapped) { - bukkitPlayer.incrementStatistic(Statistic.TRAPPED_CHEST_TRIGGERED); - } else { - bukkitPlayer.incrementStatistic(Statistic.CHEST_OPENED); - } - } - - if (block instanceof BlockShulkerBox) { - bukkitPlayer.incrementStatistic(Statistic.SHULKER_BOX_OPENED); - } - - if (block instanceof BlockBarrel) { - bukkitPlayer.incrementStatistic(Statistic.OPEN_BARREL); - } - - // AnyChest only - SilentChest not active, container unsupported, or unnecessary. - if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { - player.openContainer(tileInventory); - return true; - } - - // SilentChest requires access to setting players' gamemode directly. - if (this.playerInteractManagerGamemode == null) { - return false; - } - - if (tile instanceof TileEntityLootable) { - TileEntityLootable lootable = (TileEntityLootable) tile; - if (lootable.lootTable != null) { - OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated"); - return false; - } - } - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.openContainer(tileInventory); - this.forceGameMode(player, gamemode); - return true; - } - - @Override - public void deactivateContainer(@NotNull final Player bukkitPlayer) { - if (this.playerInteractManagerGamemode == null) { - return; - } - - InventoryView view = bukkitPlayer.getOpenInventory(); - switch (view.getType()) { - case CHEST: - case ENDER_CHEST: - case SHULKER_BOX: - case BARREL: - break; - default: - return; - } - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.activeContainer.b(player); - player.activeContainer.a(player, false); - player.activeContainer.transferTo(player.defaultContainer, player.getBukkitEntity()); - player.activeContainer = player.defaultContainer; - this.forceGameMode(player, gamemode); - } - - private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { - if (this.playerInteractManagerGamemode == null) { - // No need to warn repeatedly, error on startup and lack of function should be enough. - return; - } - try { - if (!this.playerInteractManagerGamemode.isAccessible()) { - // Just in case, ensure accessible. - this.playerInteractManagerGamemode.setAccessible(true); - } - this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); - } catch (IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - } - -} diff --git a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/PlayerDataManager.java b/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/PlayerDataManager.java deleted file mode 100644 index 23876cf..0000000 --- a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/PlayerDataManager.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_15_R1; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.internal.IPlayerDataManager; -import com.lishid.openinv.internal.ISpecialInventory; -import com.mojang.authlib.GameProfile; -import java.io.File; -import java.io.FileOutputStream; -import java.lang.reflect.Field; -import net.minecraft.server.v1_15_R1.ChatComponentText; -import net.minecraft.server.v1_15_R1.ChatMessageType; -import net.minecraft.server.v1_15_R1.Container; -import net.minecraft.server.v1_15_R1.Containers; -import net.minecraft.server.v1_15_R1.DimensionManager; -import net.minecraft.server.v1_15_R1.Entity; -import net.minecraft.server.v1_15_R1.EntityHuman; -import net.minecraft.server.v1_15_R1.EntityPlayer; -import net.minecraft.server.v1_15_R1.MinecraftServer; -import net.minecraft.server.v1_15_R1.NBTCompressedStreamTools; -import net.minecraft.server.v1_15_R1.NBTTagCompound; -import net.minecraft.server.v1_15_R1.PacketPlayOutChat; -import net.minecraft.server.v1_15_R1.PacketPlayOutOpenWindow; -import net.minecraft.server.v1_15_R1.PlayerInteractManager; -import net.minecraft.server.v1_15_R1.PlayerInventory; -import net.minecraft.server.v1_15_R1.WorldNBTStorage; -import org.apache.logging.log4j.LogManager; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.Server; -import org.bukkit.craftbukkit.v1_15_R1.CraftServer; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftContainer; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class PlayerDataManager implements IPlayerDataManager { - - private Field bukkitEntity; - - public PlayerDataManager() { - try { - bukkitEntity = Entity.class.getDeclaredField("bukkitEntity"); - } catch (NoSuchFieldException e) { - System.out.println("Unable to obtain field to inject custom save process - players' mounts may be deleted when loaded."); - e.printStackTrace(); - bukkitEntity = null; - } - } - - @NotNull - public static EntityPlayer getHandle(final Player player) { - if (player instanceof CraftPlayer) { - return ((CraftPlayer) player).getHandle(); - } - - Server server = player.getServer(); - EntityPlayer nmsPlayer = null; - - if (server instanceof CraftServer) { - nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName()); - } - - if (nmsPlayer == null) { - // Could use reflection to examine fields, but it's honestly not worth the bother. - throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation"); - } - - return nmsPlayer; - } - - @Nullable - @Override - public Player loadPlayer(@NotNull final OfflinePlayer offline) { - // Ensure player has data - if (!offline.hasPlayedBefore()) { - return null; - } - - // Create a profile and entity to load the player data - // See net.minecraft.server.PlayerList#attemptLogin - GameProfile profile = new GameProfile(offline.getUniqueId(), - offline.getName() != null ? offline.getName() : offline.getUniqueId().toString()); - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(DimensionManager.OVERWORLD), profile, - new PlayerInteractManager(server.getWorldServer(DimensionManager.OVERWORLD))); - - try { - injectPlayer(entity); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - // Get the bukkit entity - Player target = entity.getBukkitEntity(); - if (target != null) { - // Load data - target.loadData(); - } - // Return the entity - return target; - } - - void injectPlayer(EntityPlayer player) throws IllegalAccessException { - if (bukkitEntity == null) { - return; - } - - bukkitEntity.setAccessible(true); - - bukkitEntity.set(player, new CraftPlayer(player.server.server, player) { - @Override - public void saveData() { - super.saveData(); - // See net.minecraft.server.WorldNBTStorage#save(EntityPlayer) - try { - WorldNBTStorage worldNBTStorage = (WorldNBTStorage) player.server.getPlayerList().playerFileData; - - NBTTagCompound playerData = player.save(new NBTTagCompound()); - - if (!isOnline()) { - // Special case: save old vehicle data - NBTTagCompound oldData = worldNBTStorage.load(player); - - if (oldData != null && oldData.hasKeyOfType("RootVehicle", 10)) { - // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) - playerData.set("RootVehicle", oldData.getCompound("RootVehicle")); - } - } - - File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat.tmp"); - File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat"); - - NBTCompressedStreamTools.a(playerData, new FileOutputStream(file)); - - if (file1.exists()) { - file1.delete(); - } - - file.renameTo(file1); - } catch (Exception e) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); - } - } - }); - } - - @NotNull - @Override - public Player inject(@NotNull Player player) { - try { - EntityPlayer nmsPlayer = getHandle(player); - injectPlayer(nmsPlayer); - return nmsPlayer.getBukkitEntity(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return player; - } - } - - @Nullable - @Override - public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) { - - EntityPlayer nmsPlayer = getHandle(player); - - if (nmsPlayer.playerConnection == null) { - return null; - } - - String title; - if (inventory instanceof SpecialEnderChest) { - HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner(); - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.enderchest", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Ender Chest"; - } - } else if (inventory instanceof SpecialPlayerInventory) { - EntityHuman owner = ((PlayerInventory) inventory).player; - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.player", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Inventory"; - } - } else { - return player.openInventory(inventory.getBukkitInventory()); - } - - String finalTitle = title; - Container container = new CraftContainer(new InventoryView() { - @Override - public @NotNull Inventory getTopInventory() { - return inventory.getBukkitInventory(); - } - @Override - public @NotNull Inventory getBottomInventory() { - return player.getInventory(); - } - @Override - public @NotNull HumanEntity getPlayer() { - return player; - } - @Override - public @NotNull InventoryType getType() { - return inventory.getBukkitInventory().getType(); - } - @Override - public @NotNull String getTitle() { - return finalTitle; - } - }, nmsPlayer, nmsPlayer.nextContainerCounter()) { - @Override - public Containers getType() { - switch (inventory.getBukkitInventory().getSize()) { - case 9: - return Containers.GENERIC_9X1; - case 18: - return Containers.GENERIC_9X2; - case 27: - default: - return Containers.GENERIC_9X3; - case 36: - return Containers.GENERIC_9X4; - case 41: // PLAYER - case 45: - return Containers.GENERIC_9X5; - case 54: - return Containers.GENERIC_9X6; - } - } - }; - - container.setTitle(new ChatComponentText(title)); - container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); - - if (container == null) { - return null; - } - - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), - new ChatComponentText(container.getBukkitView().getTitle()))); - nmsPlayer.activeContainer = container; - container.addSlotListener(nmsPlayer); - - return container.getBukkitView(); - - } - - @Override - public void sendSystemMessage(@NotNull Player player, @NotNull String message) { - int newline = message.indexOf('\n'); - if (newline != -1) { - // No newlines in action bar chat. - message = message.substring(0, newline); - } - - if (message.isEmpty()) { - return; - } - - EntityPlayer nmsPlayer = getHandle(player); - - // For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text. - if (nmsPlayer.playerConnection != null) { - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO)); - } - } - -} diff --git a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialEnderChest.java b/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialEnderChest.java deleted file mode 100644 index de70b04..0000000 --- a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialEnderChest.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_15_R1; - -import com.lishid.openinv.internal.ISpecialEnderChest; -import java.util.List; -import net.minecraft.server.v1_15_R1.AutoRecipeStackManager; -import net.minecraft.server.v1_15_R1.ContainerUtil; -import net.minecraft.server.v1_15_R1.EntityHuman; -import net.minecraft.server.v1_15_R1.EntityPlayer; -import net.minecraft.server.v1_15_R1.IInventoryListener; -import net.minecraft.server.v1_15_R1.InventoryEnderChest; -import net.minecraft.server.v1_15_R1.ItemStack; -import net.minecraft.server.v1_15_R1.NonNullList; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEnderChest { - - private final CraftInventory inventory; - private EntityPlayer owner; - private NonNullList items; - private boolean playerOnline; - - public SpecialEnderChest(final Player player, final Boolean online) { - super(PlayerDataManager.getHandle(player)); - this.inventory = new CraftInventory(this); - this.owner = PlayerDataManager.getHandle(player); - this.playerOnline = online; - this.items = this.owner.getEnderChest().items; - } - - @Override - public @NotNull CraftInventory getBukkitInventory() { - return inventory; - } - - @Override - public boolean isInUse() { - return !this.getViewers().isEmpty(); - } - - @Override - public void setPlayerOffline() { - this.playerOnline = false; - } - - @Override - public void setPlayerOnline(@NotNull final Player player) { - if (!this.playerOnline) { - try { - this.owner = PlayerDataManager.getHandle(player); - InventoryEnderChest enderChest = owner.getEnderChest(); - for (int i = 0; i < enderChest.getSize(); ++i) { - enderChest.setItem(i, this.items.get(i)); - } - this.items = enderChest.items; - } catch (Exception ignored) {} - this.playerOnline = true; - } - } - - @Override - public void update() { - this.owner.getEnderChest().update(); - } - - @Override - public List getContents() { - return this.items; - } - - @Override - public void onOpen(CraftHumanEntity who) { - this.owner.getEnderChest().onOpen(who); - } - - @Override - public void onClose(CraftHumanEntity who) { - this.owner.getEnderChest().onClose(who); - } - - @Override - public List getViewers() { - return this.owner.getEnderChest().getViewers(); - } - - @Override - public void setMaxStackSize(int i) { - this.owner.getEnderChest().setMaxStackSize(i); - } - - @Override - public InventoryHolder getOwner() { - return this.owner.getEnderChest().getOwner(); - } - - @Override - public @Nullable Location getLocation() { - return null; - } - - @Override - public void a(IInventoryListener iinventorylistener) { - this.owner.getEnderChest().a(iinventorylistener); - } - - @Override - public void b(IInventoryListener iinventorylistener) { - this.owner.getEnderChest().b(iinventorylistener); - } - - @Override - public ItemStack getItem(int i) { - return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.a; - } - - @Override - public ItemStack splitStack(int i, int j) { - ItemStack itemstack = ContainerUtil.a(this.items, i, j); - if (!itemstack.isEmpty()) { - this.update(); - } - - return itemstack; - } - - @Override - public ItemStack a(ItemStack itemstack) { - ItemStack itemstack1 = itemstack.cloneItemStack(); - - for (int i = 0; i < this.getSize(); ++i) { - ItemStack itemstack2 = this.getItem(i); - if (itemstack2.isEmpty()) { - this.setItem(i, itemstack1); - this.update(); - return ItemStack.a; - } - - if (ItemStack.c(itemstack2, itemstack1)) { - int j = Math.min(this.getMaxStackSize(), itemstack2.getMaxStackSize()); - int k = Math.min(itemstack1.getCount(), j - itemstack2.getCount()); - if (k > 0) { - itemstack2.add(k); - itemstack1.subtract(k); - if (itemstack1.isEmpty()) { - this.update(); - return ItemStack.a; - } - } - } - } - - if (itemstack1.getCount() != itemstack.getCount()) { - this.update(); - } - - return itemstack1; - } - - @Override - public ItemStack splitWithoutUpdate(int i) { - ItemStack itemstack = this.items.get(i); - if (itemstack.isEmpty()) { - return ItemStack.a; - } else { - this.items.set(i, ItemStack.a); - return itemstack; - } - } - - @Override - public void setItem(int i, ItemStack itemstack) { - this.items.set(i, itemstack); - if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) { - itemstack.setCount(this.getMaxStackSize()); - } - - this.update(); - } - - @Override - public int getSize() { - return this.owner.getEnderChest().getSize(); - } - - @Override - public boolean isEmpty() { - - for (ItemStack itemstack : this.items) { - if (!itemstack.isEmpty()) { - return false; - } - } - - return true; - } - - @Override - public int getMaxStackSize() { - return 64; - } - - @Override - public boolean a(EntityHuman entityhuman) { - return true; - } - - @Override - public void startOpen(EntityHuman entityhuman) { - } - - @Override - public void closeContainer(EntityHuman entityhuman) { - } - - @Override - public boolean b(int i, ItemStack itemstack) { - return true; - } - - @Override - public void clear() { - this.items.clear(); - } - - @Override - public void a(AutoRecipeStackManager autorecipestackmanager) { - - for (ItemStack itemstack : this.items) { - autorecipestackmanager.b(itemstack); - } - - } - -} diff --git a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialPlayerInventory.java b/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialPlayerInventory.java deleted file mode 100644 index ff59d3c..0000000 --- a/internal/v1_15_R1/src/main/java/com/lishid/openinv/internal/v1_15_R1/SpecialPlayerInventory.java +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_15_R1; - -import com.google.common.collect.ImmutableList; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import net.minecraft.server.v1_15_R1.AutoRecipeStackManager; -import net.minecraft.server.v1_15_R1.ChatMessage; -import net.minecraft.server.v1_15_R1.ContainerUtil; -import net.minecraft.server.v1_15_R1.CrashReport; -import net.minecraft.server.v1_15_R1.CrashReportSystemDetails; -import net.minecraft.server.v1_15_R1.EntityHuman; -import net.minecraft.server.v1_15_R1.EntityPlayer; -import net.minecraft.server.v1_15_R1.EnumItemSlot; -import net.minecraft.server.v1_15_R1.IBlockData; -import net.minecraft.server.v1_15_R1.IChatBaseComponent; -import net.minecraft.server.v1_15_R1.Item; -import net.minecraft.server.v1_15_R1.ItemArmor; -import net.minecraft.server.v1_15_R1.ItemStack; -import net.minecraft.server.v1_15_R1.NBTTagCompound; -import net.minecraft.server.v1_15_R1.NBTTagList; -import net.minecraft.server.v1_15_R1.NonNullList; -import net.minecraft.server.v1_15_R1.PacketPlayOutSetSlot; -import net.minecraft.server.v1_15_R1.PlayerInventory; -import net.minecraft.server.v1_15_R1.ReportedException; -import net.minecraft.server.v1_15_R1.World; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { - - private final CraftInventory inventory; - private boolean playerOnline; - private EntityHuman player; - private NonNullList items, armor, extraSlots; - private List> f; - - public SpecialPlayerInventory(final Player bukkitPlayer, final Boolean online) { - super(PlayerDataManager.getHandle(bukkitPlayer)); - this.inventory = new CraftInventory(this); - this.playerOnline = online; - this.player = super.player; - this.items = this.player.inventory.items; - this.armor = this.player.inventory.armor; - this.extraSlots = this.player.inventory.extraSlots; - this.f = ImmutableList.of(this.items, this.armor, this.extraSlots); - } - - @Override - public void setPlayerOnline(@NotNull final Player player) { - if (!this.playerOnline) { - EntityPlayer entityPlayer = PlayerDataManager.getHandle(player); - entityPlayer.inventory.transaction.addAll(this.transaction); - this.player = entityPlayer; - for (int i = 0; i < getSize(); ++i) { - this.player.inventory.setItem(i, getRawItem(i)); - } - this.player.inventory.itemInHandIndex = this.itemInHandIndex; - this.items = this.player.inventory.items; - this.armor = this.player.inventory.armor; - this.extraSlots = this.player.inventory.extraSlots; - this.f = ImmutableList.of(this.items, this.armor, this.extraSlots); - this.playerOnline = true; - } - } - - @Override - public boolean a(final EntityHuman entityhuman) { - return true; - } - - @Override - public @NotNull CraftInventory getBukkitInventory() { - return this.inventory; - } - - @Override - public ItemStack getItem(int i) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.a; - } - - return list.get(i); - } - - private ItemStack getRawItem(int i) { - NonNullList list = null; - for (NonNullList next : this.f) { - if (i < next.size()) { - list = next; - break; - } - i -= next.size(); - } - - return list == null ? ItemStack.a : list.get(i); - } - - @Override - public IChatBaseComponent getDisplayName() { - return new ChatMessage(this.player.getName()); - } - - @Override - public boolean hasCustomName() { - return false; - } - - private int getReversedArmorSlotNum(final int i) { - if (i == 0) { - return 3; - } - if (i == 1) { - return 2; - } - if (i == 2) { - return 1; - } - if (i == 3) { - return 0; - } - return i; - } - - private int getReversedItemSlotNum(final int i) { - if (i >= 27) { - return i - 27; - } - return i + 9; - } - - @Override - public int getSize() { - return 45; - } - - @Override - public boolean isInUse() { - return !this.getViewers().isEmpty(); - } - - @Override - public void setItem(int i, final ItemStack itemstack) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - this.player.drop(itemstack, true); - return; - } - - list.set(i, itemstack); - } - - @Override - public void setPlayerOffline() { - this.playerOnline = false; - } - - @Override - public ItemStack splitStack(int i, final int j) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.a; - } - - return list.get(i).isEmpty() ? ItemStack.a : ContainerUtil.a(list, i, j); - } - - @Override - public ItemStack splitWithoutUpdate(int i) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.a; - } - - if (!list.get(i).isEmpty()) { - ItemStack itemstack = list.get(i); - - list.set(i, ItemStack.a); - return itemstack; - } - - return ItemStack.a; - } - - @Override - public List getContents() { - return this.f.stream().flatMap(List::stream).collect(Collectors.toList()); - } - - @Override - public List getArmorContents() { - return this.armor; - } - - @Override - public void onOpen(CraftHumanEntity who) { - this.transaction.add(who); - } - - @Override - public void onClose(CraftHumanEntity who) { - this.transaction.remove(who); - } - - @Override - public List getViewers() { - return this.transaction; - } - - @Override - public InventoryHolder getOwner() { - return this.player.getBukkitEntity(); - } - - @Override - public Location getLocation() { - return this.player.getBukkitEntity().getLocation(); - } - - @Override - public ItemStack getItemInHand() { - return d(this.itemInHandIndex) ? this.items.get(this.itemInHandIndex) : ItemStack.a; - } - - private boolean a(ItemStack itemstack, ItemStack itemstack1) { - return !itemstack.isEmpty() && this.b(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize(); - } - - private boolean b(ItemStack itemstack, ItemStack itemstack1) { - return itemstack.getItem() == itemstack1.getItem() && ItemStack.equals(itemstack, itemstack1); - } - - @Override - public int canHold(ItemStack itemstack) { - int remains = itemstack.getCount(); - - for (int i = 0; i < this.items.size(); ++i) { - ItemStack itemstack1 = this.getItem(i); - if (itemstack1.isEmpty()) { - return itemstack.getCount(); - } - - if (!this.a(itemstack, itemstack1)) { - remains -= Math.min(itemstack1.getMaxStackSize(), this.getMaxStackSize()) - itemstack1.getCount(); - } - - if (remains <= 0) { - return itemstack.getCount(); - } - } - - return itemstack.getCount() - remains; - } - - @Override - public int getFirstEmptySlotIndex() { - for (int i = 0; i < this.items.size(); ++i) { - if (this.items.get(i).isEmpty()) { - return i; - } - } - - return -1; - } - - @Override - public void c(int i) { - this.itemInHandIndex = this.i(); - ItemStack itemstack = this.items.get(this.itemInHandIndex); - this.items.set(this.itemInHandIndex, this.items.get(i)); - this.items.set(i, itemstack); - } - - @Override - public int c(ItemStack itemstack) { - for (int i = 0; i < this.items.size(); ++i) { - ItemStack itemstack1 = this.items.get(i); - if (!this.items.get(i).isEmpty() && this.b(itemstack, this.items.get(i)) && !this.items.get(i).f() && !itemstack1.hasEnchantments() && !itemstack1.hasName()) { - return i; - } - } - - return -1; - } - - @Override - public int i() { - int i; - int j; - for (j = 0; j < 9; ++j) { - i = (this.itemInHandIndex + j) % 9; - if (this.items.get(i).isEmpty()) { - return i; - } - } - - for (j = 0; j < 9; ++j) { - i = (this.itemInHandIndex + j) % 9; - if (!this.items.get(i).hasEnchantments()) { - return i; - } - } - - return this.itemInHandIndex; - } - - @Override - public int a(Predicate predicate, int i) { - int j = 0; - - int k; - for (k = 0; k < this.getSize(); ++k) { - ItemStack itemstack = this.getItem(k); - if (!itemstack.isEmpty() && predicate.test(itemstack)) { - int l = i <= 0 ? itemstack.getCount() : Math.min(i - j, itemstack.getCount()); - j += l; - if (i != 0) { - itemstack.subtract(l); - if (itemstack.isEmpty()) { - this.setItem(k, ItemStack.a); - } - - if (i > 0 && j >= i) { - return j; - } - } - } - } - - if (!this.getCarried().isEmpty() && predicate.test(this.getCarried())) { - k = i <= 0 ? this.getCarried().getCount() : Math.min(i - j, this.getCarried().getCount()); - j += k; - if (i != 0) { - this.getCarried().subtract(k); - if (this.getCarried().isEmpty()) { - this.setCarried(ItemStack.a); - } - - if (i > 0 && j >= i) { - return j; - } - } - } - - return j; - } - - private int i(ItemStack itemstack) { - int i = this.firstPartial(itemstack); - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - return i == -1 ? itemstack.getCount() : this.d(i, itemstack); - } - - private int d(int i, ItemStack itemstack) { - Item item = itemstack.getItem(); - int j = itemstack.getCount(); - ItemStack itemstack1 = this.getItem(i); - if (itemstack1.isEmpty()) { - itemstack1 = new ItemStack(item, 0); - if (itemstack.hasTag()) { - itemstack1.setTag(itemstack.getTag().clone()); - } - - this.setItem(i, itemstack1); - } - - int k = j; - if (j > itemstack1.getMaxStackSize() - itemstack1.getCount()) { - k = itemstack1.getMaxStackSize() - itemstack1.getCount(); - } - - if (k > this.getMaxStackSize() - itemstack1.getCount()) { - k = this.getMaxStackSize() - itemstack1.getCount(); - } - - if (k != 0) { - j -= k; - itemstack1.add(k); - itemstack1.d(5); - } - return j; - } - - @Override - public int firstPartial(ItemStack itemstack) { - if (this.a(this.getItem(this.itemInHandIndex), itemstack)) { - return this.itemInHandIndex; - } else if (this.a(this.getItem(40), itemstack)) { - return 40; - } else { - for (int i = 0; i < this.items.size(); ++i) { - if (this.a(this.items.get(i), itemstack)) { - return i; - } - } - - return -1; - } - } - - @Override - public void j() { - - for (List itemStacks : this.f) { - for (int i = 0; i < itemStacks.size(); ++i) { - if (!itemStacks.get(i).isEmpty()) { - itemStacks.get(i).a(this.player.world, this.player, i, this.itemInHandIndex == i); - } - } - } - - } - - @Override - public boolean pickup(ItemStack itemstack) { - return this.c(-1, itemstack); - } - - @Override - public boolean c(int i, ItemStack itemstack) { - if (itemstack.isEmpty()) { - return false; - } else { - try { - if (itemstack.f()) { - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - if (i >= 0) { - this.items.set(i, itemstack.cloneItemStack()); - this.items.get(i).d(5); - itemstack.setCount(0); - return true; - } else if (this.player.abilities.canInstantlyBuild) { - itemstack.setCount(0); - return true; - } else { - return false; - } - } else { - int j; - do { - j = itemstack.getCount(); - if (i == -1) { - itemstack.setCount(this.i(itemstack)); - } else { - itemstack.setCount(this.d(i, itemstack)); - } - } while(!itemstack.isEmpty() && itemstack.getCount() < j); - - if (itemstack.getCount() == j && this.player.abilities.canInstantlyBuild) { - itemstack.setCount(0); - return true; - } else { - return itemstack.getCount() < j; - } - } - } catch (Throwable var6) { - CrashReport crashreport = CrashReport.a(var6, "Adding item to inventory"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Item being added"); - crashreportsystemdetails.a("Item ID", Item.getId(itemstack.getItem())); - crashreportsystemdetails.a("Item data", itemstack.getDamage()); - crashreportsystemdetails.a("Item name", () -> itemstack.getName().getString()); - throw new ReportedException(crashreport); - } - } - } - - @Override - public void a(World world, ItemStack itemstack) { - if (!world.isClientSide) { - while(!itemstack.isEmpty()) { - int i = this.firstPartial(itemstack); - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - if (i == -1) { - this.player.drop(itemstack, false); - break; - } - - int j = itemstack.getMaxStackSize() - this.getItem(i).getCount(); - if (this.c(i, itemstack.cloneAndSubtract(j))) { - ((EntityPlayer)this.player).playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, i, this.getItem(i))); - } - } - } - - } - - @Override - public void f(ItemStack itemstack) { - - for (List list : this.f) { - for (int i = 0; i < list.size(); ++i) { - if (list.get(i) == itemstack) { - list.set(i, ItemStack.a); - break; - } - } - } - } - - @Override - public float a(IBlockData iblockdata) { - return this.items.get(this.itemInHandIndex).a(iblockdata); - } - - @Override - public NBTTagList a(NBTTagList nbttaglist) { - NBTTagCompound nbttagcompound; - int i; - for (i = 0; i < this.items.size(); ++i) { - if (!this.items.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) i); - this.items.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - for (i = 0; i < this.armor.size(); ++i) { - if (!this.armor.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) (i + 100)); - this.armor.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - for (i = 0; i < this.extraSlots.size(); ++i) { - if (!this.extraSlots.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) (i + 150)); - this.extraSlots.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - return nbttaglist; - } - - @Override - public void b(NBTTagList nbttaglist) { - this.items.clear(); - this.armor.clear(); - this.extraSlots.clear(); - - for(int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound = nbttaglist.getCompound(i); - int j = nbttagcompound.getByte("Slot") & 255; - ItemStack itemstack = ItemStack.a(nbttagcompound); - if (!itemstack.isEmpty()) { - if (j < this.items.size()) { - this.items.set(j, itemstack); - } else if (j >= 100 && j < this.armor.size() + 100) { - this.armor.set(j - 100, itemstack); - } else if (j >= 150 && j < this.extraSlots.size() + 150) { - this.extraSlots.set(j - 150, itemstack); - } - } - } - - } - - @Override - public boolean isEmpty() { - Iterator iterator = this.items.iterator(); - - ItemStack itemstack; - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - iterator = this.armor.iterator(); - - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - iterator = this.extraSlots.iterator(); - - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - return true; - } - - @Nullable - @Override - public IChatBaseComponent getCustomName() { - return null; - } - - @Override - public boolean b(IBlockData iblockdata) { - return this.getItem(this.itemInHandIndex).canDestroySpecialBlock(iblockdata); - } - - @Override - public void a(float f) { - if (f > 0.0F) { - f /= 4.0F; - if (f < 1.0F) { - f = 1.0F; - } - - for (int i = 0; i < this.armor.size(); ++i) { - ItemStack itemstack = this.armor.get(0); - int index = i; - if (itemstack.getItem() instanceof ItemArmor) { - itemstack.damage((int) f, this.player, (entityhuman) -> entityhuman.broadcastItemBreak(EnumItemSlot.a(EnumItemSlot.Function.ARMOR, index))); - } - } - } - } - - @Override - public void dropContents() { - for (List itemStacks : this.f) { - for (int i = 0; i < itemStacks.size(); ++i) { - ItemStack itemstack = itemStacks.get(i); - if (!itemstack.isEmpty()) { - itemStacks.set(i, ItemStack.a); - this.player.a(itemstack, true, false); - } - } - } - } - - @Override - public boolean h(ItemStack itemstack) { - return this.f.stream().flatMap(List::stream).anyMatch(itemStack1 -> !itemStack1.isEmpty() && itemStack1.doMaterialsMatch(itemstack)); - } - - @Override - public void a(PlayerInventory playerinventory) { - for (int i = 0; i < playerinventory.getSize(); ++i) { - this.setItem(i, playerinventory.getItem(i)); - } - - this.itemInHandIndex = playerinventory.itemInHandIndex; - } - - @Override - public void clear() { - this.f.forEach(List::clear); - } - - @Override - public void a(AutoRecipeStackManager autorecipestackmanager) { - for (ItemStack itemstack : this.items) { - autorecipestackmanager.a(itemstack); - } - } - -} diff --git a/internal/v1_16_R2/pom.xml b/internal/v1_16_R2/pom.xml deleted file mode 100644 index f72ab8f..0000000 --- a/internal/v1_16_R2/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.6-SNAPSHOT - - - openinvadapter1_16_R2 - OpenInvAdapter1_16_R2 - - - - org.spigotmc - spigot - 1.16.3-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.6-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.2 - - true - - - - package - - shade - - - - - - - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - - \ No newline at end of file diff --git a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/AnySilentContainer.java b/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/AnySilentContainer.java deleted file mode 100644 index 4040449..0000000 --- a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/AnySilentContainer.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_16_R2; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.internal.IAnySilentContainer; -import java.lang.reflect.Field; -import net.minecraft.server.v1_16_R2.Block; -import net.minecraft.server.v1_16_R2.BlockBarrel; -import net.minecraft.server.v1_16_R2.BlockChest; -import net.minecraft.server.v1_16_R2.BlockChestTrapped; -import net.minecraft.server.v1_16_R2.BlockPosition; -import net.minecraft.server.v1_16_R2.BlockPropertyChestType; -import net.minecraft.server.v1_16_R2.BlockShulkerBox; -import net.minecraft.server.v1_16_R2.ChatMessage; -import net.minecraft.server.v1_16_R2.Container; -import net.minecraft.server.v1_16_R2.ContainerChest; -import net.minecraft.server.v1_16_R2.Containers; -import net.minecraft.server.v1_16_R2.EntityHuman; -import net.minecraft.server.v1_16_R2.EntityPlayer; -import net.minecraft.server.v1_16_R2.EnumGamemode; -import net.minecraft.server.v1_16_R2.IBlockData; -import net.minecraft.server.v1_16_R2.IChatBaseComponent; -import net.minecraft.server.v1_16_R2.ITileInventory; -import net.minecraft.server.v1_16_R2.InventoryEnderChest; -import net.minecraft.server.v1_16_R2.InventoryLargeChest; -import net.minecraft.server.v1_16_R2.PlayerInteractManager; -import net.minecraft.server.v1_16_R2.PlayerInventory; -import net.minecraft.server.v1_16_R2.TileEntity; -import net.minecraft.server.v1_16_R2.TileEntityChest; -import net.minecraft.server.v1_16_R2.TileEntityEnderChest; -import net.minecraft.server.v1_16_R2.TileEntityLootable; -import net.minecraft.server.v1_16_R2.TileInventory; -import net.minecraft.server.v1_16_R2.World; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.block.Barrel; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.EnderChest; -import org.bukkit.block.ShulkerBox; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.type.Chest; -import org.bukkit.entity.Cat; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryView; -import org.bukkit.util.BoundingBox; -import org.jetbrains.annotations.NotNull; - -public class AnySilentContainer implements IAnySilentContainer { - - private Field playerInteractManagerGamemode; - - public AnySilentContainer() { - try { - this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); - this.playerInteractManagerGamemode.setAccessible(true); - } catch (NoSuchFieldException | SecurityException e) { - System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); - e.printStackTrace(); - } - } - - @Override - public boolean isAnySilentContainer(@NotNull final org.bukkit.block.Block bukkitBlock) { - if (bukkitBlock.getType() == Material.ENDER_CHEST) { - return true; - } - BlockState state = bukkitBlock.getState(); - return state instanceof org.bukkit.block.Chest - || state instanceof org.bukkit.block.ShulkerBox - || state instanceof org.bukkit.block.Barrel; - } - - @Override - public boolean isAnyContainerNeeded(@NotNull final Player p, @NotNull final org.bukkit.block.Block block) { - BlockState blockState = block.getState(); - - // Barrels do not require AnyContainer. - if (blockState instanceof Barrel) { - return false; - } - - // Enderchests require a non-occluding block on top to open. - if (blockState instanceof EnderChest) { - return block.getRelative(0, 1, 0).getType().isOccluding(); - } - - // Shulker boxes require 1/2 a block clear in the direction they open. - if (blockState instanceof ShulkerBox) { - BoundingBox boundingBox = block.getBoundingBox(); - if (boundingBox.getVolume() > 1) { - // Shulker box is already open. - return false; - } - - BlockData blockData = block.getBlockData(); - if (!(blockData instanceof Directional)) { - // Shouldn't be possible. Just in case, demand AnyChest. - return true; - } - - Directional directional = (Directional) blockData; - BlockFace face = directional.getFacing(); - boundingBox.shift(face.getDirection()); - // Return whether or not bounding boxes overlap. - return block.getRelative(face, 1).getBoundingBox().overlaps(boundingBox); - } - - if (!(blockState instanceof org.bukkit.block.Chest)) { - return false; - } - - if (isBlockedChest(block)) { - return true; - } - - BlockData blockData = block.getBlockData(); - if (!(blockData instanceof Chest) || ((Chest) blockData).getType() == Chest.Type.SINGLE) { - return false; - } - - Chest chest = (Chest) blockData; - int ordinal = (chest.getFacing().ordinal() + 4 + (chest.getType() == Chest.Type.RIGHT ? -1 : 1)) % 4; - BlockFace relativeFace = BlockFace.values()[ordinal]; - org.bukkit.block.Block relative = block.getRelative(relativeFace); - - if (relative.getType() != block.getType()) { - return false; - } - - BlockData relativeData = relative.getBlockData(); - if (!(relativeData instanceof Chest)) { - return false; - } - - Chest relativeChest = (Chest) relativeData; - if (relativeChest.getFacing() != chest.getFacing() - || relativeChest.getType() != (chest.getType() == Chest.Type.RIGHT ? Chest.Type.LEFT : Chest.Type.RIGHT)) { - return false; - } - - return isBlockedChest(relative); - } - - private boolean isBlockedChest(org.bukkit.block.Block block) { - org.bukkit.block.Block relative = block.getRelative(0, 1, 0); - return relative.getType().isOccluding() - || block.getWorld().getNearbyEntities(BoundingBox.of(relative), entity -> entity instanceof Cat).size() > 0; - } - - @Override - public boolean activateContainer(@NotNull final Player bukkitPlayer, final boolean silentchest, - @NotNull final org.bukkit.block.Block bukkitBlock) { - - // Silent ender chest is API-only - if (silentchest && bukkitBlock.getType() == Material.ENDER_CHEST) { - bukkitPlayer.openInventory(bukkitPlayer.getEnderChest()); - bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED); - return true; - } - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - final World world = player.world; - final BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ()); - final TileEntity 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(new TileInventory((containerCounter, playerInventory, ignored) -> { - Containers containers; - int rows = enderChest.getSize() / 9; - switch (rows) { - case 1: - containers = Containers.GENERIC_9X1; - break; - case 2: - containers = Containers.GENERIC_9X2; - break; - case 3: - default: - containers = Containers.GENERIC_9X3; - break; - case 4: - containers = Containers.GENERIC_9X4; - break; - case 5: - containers = Containers.GENERIC_9X5; - break; - case 6: - containers = Containers.GENERIC_9X6; - break; - } - return new ContainerChest(containers, containerCounter, playerInventory, enderChest, rows); - }, new ChatMessage("container.enderchest"))); - bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED); - return true; - } - - if (!(tile instanceof ITileInventory)) { - return false; - } - - ITileInventory tileInventory = (ITileInventory) tile; - IBlockData blockData = world.getType(blockPosition); - Block block = blockData.getBlock(); - - if (block instanceof BlockChest) { - - BlockPropertyChestType chestType = blockData.get(BlockChest.c); - - if (chestType != BlockPropertyChestType.SINGLE) { - - BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.h(blockData)); - IBlockData adjacentBlockData = world.getType(adjacentBlockPosition); - - if (adjacentBlockData.getBlock() == block) { - - BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.c); - - if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType - && adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) { - - TileEntity adjacentTile = world.getTileEntity(adjacentBlockPosition); - - if (adjacentTile instanceof TileEntityChest && tileInventory instanceof TileEntityChest) { - TileEntityChest rightChest = chestType == BlockPropertyChestType.RIGHT ? ((TileEntityChest) tileInventory) : (TileEntityChest) adjacentTile; - TileEntityChest leftChest = chestType == BlockPropertyChestType.RIGHT ? (TileEntityChest) adjacentTile : ((TileEntityChest) tileInventory); - - if (silentchest && (rightChest.lootTable != null || leftChest.lootTable != null)) { - OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated"); - return false; - } - - tileInventory = new ITileInventory() { - public Container createMenu(int containerCounter, PlayerInventory playerInventory, EntityHuman entityHuman) { - leftChest.d(playerInventory.player); - rightChest.d(playerInventory.player); - return ContainerChest.b(containerCounter, playerInventory, new InventoryLargeChest(rightChest, leftChest)); - } - - public IChatBaseComponent getScoreboardDisplayName() { - return new ChatMessage("container.chestDouble"); - } - }; - } - } - } - } - - if (block instanceof BlockChestTrapped) { - bukkitPlayer.incrementStatistic(Statistic.TRAPPED_CHEST_TRIGGERED); - } else { - bukkitPlayer.incrementStatistic(Statistic.CHEST_OPENED); - } - } - - if (block instanceof BlockShulkerBox) { - bukkitPlayer.incrementStatistic(Statistic.SHULKER_BOX_OPENED); - } - - if (block instanceof BlockBarrel) { - bukkitPlayer.incrementStatistic(Statistic.OPEN_BARREL); - } - - // AnyChest only - SilentChest not active, container unsupported, or unnecessary. - if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { - player.openContainer(tileInventory); - return true; - } - - // SilentChest requires access to setting players' gamemode directly. - if (this.playerInteractManagerGamemode == null) { - return false; - } - - if (tile instanceof TileEntityLootable) { - TileEntityLootable lootable = (TileEntityLootable) tile; - if (lootable.lootTable != null) { - OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated"); - return false; - } - } - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.openContainer(tileInventory); - this.forceGameMode(player, gamemode); - return true; - } - - @Override - public void deactivateContainer(@NotNull final Player bukkitPlayer) { - if (this.playerInteractManagerGamemode == null) { - return; - } - - InventoryView view = bukkitPlayer.getOpenInventory(); - switch (view.getType()) { - case CHEST: - case ENDER_CHEST: - case SHULKER_BOX: - case BARREL: - break; - default: - return; - } - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.activeContainer.b(player); - player.activeContainer.a(player, false); - player.activeContainer.transferTo(player.defaultContainer, player.getBukkitEntity()); - player.activeContainer = player.defaultContainer; - this.forceGameMode(player, gamemode); - } - - private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { - if (this.playerInteractManagerGamemode == null) { - // No need to warn repeatedly, error on startup and lack of function should be enough. - return; - } - try { - if (!this.playerInteractManagerGamemode.isAccessible()) { - // Just in case, ensure accessible. - this.playerInteractManagerGamemode.setAccessible(true); - } - this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); - } catch (IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - } - -} diff --git a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/PlayerDataManager.java b/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/PlayerDataManager.java deleted file mode 100644 index 79a0743..0000000 --- a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/PlayerDataManager.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_16_R2; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.internal.IPlayerDataManager; -import com.lishid.openinv.internal.ISpecialInventory; -import com.mojang.authlib.GameProfile; -import java.io.File; -import java.io.FileOutputStream; -import java.lang.reflect.Field; -import net.minecraft.server.v1_16_R2.ChatComponentText; -import net.minecraft.server.v1_16_R2.ChatMessageType; -import net.minecraft.server.v1_16_R2.Container; -import net.minecraft.server.v1_16_R2.Containers; -import net.minecraft.server.v1_16_R2.Entity; -import net.minecraft.server.v1_16_R2.EntityHuman; -import net.minecraft.server.v1_16_R2.EntityPlayer; -import net.minecraft.server.v1_16_R2.MinecraftServer; -import net.minecraft.server.v1_16_R2.NBTCompressedStreamTools; -import net.minecraft.server.v1_16_R2.NBTTagCompound; -import net.minecraft.server.v1_16_R2.PacketPlayOutChat; -import net.minecraft.server.v1_16_R2.PacketPlayOutOpenWindow; -import net.minecraft.server.v1_16_R2.PlayerInteractManager; -import net.minecraft.server.v1_16_R2.PlayerInventory; -import net.minecraft.server.v1_16_R2.SystemUtils; -import net.minecraft.server.v1_16_R2.World; -import net.minecraft.server.v1_16_R2.WorldNBTStorage; -import net.minecraft.server.v1_16_R2.WorldServer; -import org.apache.logging.log4j.LogManager; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.Server; -import org.bukkit.craftbukkit.v1_16_R2.CraftServer; -import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_16_R2.event.CraftEventFactory; -import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftContainer; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class PlayerDataManager implements IPlayerDataManager { - - private @Nullable Field bukkitEntity; - - public PlayerDataManager() { - try { - bukkitEntity = Entity.class.getDeclaredField("bukkitEntity"); - } catch (NoSuchFieldException e) { - System.out.println("Unable to obtain field to inject custom save process - players' mounts may be deleted when loaded."); - e.printStackTrace(); - bukkitEntity = null; - } - } - - @NotNull - public static EntityPlayer getHandle(final Player player) { - if (player instanceof CraftPlayer) { - return ((CraftPlayer) player).getHandle(); - } - - Server server = player.getServer(); - EntityPlayer nmsPlayer = null; - - if (server instanceof CraftServer) { - nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName()); - } - - if (nmsPlayer == null) { - // Could use reflection to examine fields, but it's honestly not worth the bother. - throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation"); - } - - return nmsPlayer; - } - - @Nullable - @Override - public Player loadPlayer(@NotNull final OfflinePlayer offline) { - // Ensure player has data - if (!offline.hasPlayedBefore()) { - return null; - } - - // Create a profile and entity to load the player data - // See net.minecraft.server.PlayerList#attemptLogin - GameProfile profile = new GameProfile(offline.getUniqueId(), - offline.getName() != null ? offline.getName() : offline.getUniqueId().toString()); - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - WorldServer worldServer = server.getWorldServer(World.OVERWORLD); - - if (worldServer == null) { - return null; - } - - EntityPlayer entity = new EntityPlayer(server, worldServer, profile, new PlayerInteractManager(worldServer)); - - try { - injectPlayer(entity); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - // Get the bukkit entity - Player target = entity.getBukkitEntity(); - if (target != null) { - // Load data - target.loadData(); - } - // Return the entity - return target; - } - - void injectPlayer(EntityPlayer player) throws IllegalAccessException { - if (bukkitEntity == null) { - return; - } - - bukkitEntity.setAccessible(true); - - bukkitEntity.set(player, new CraftPlayer(player.server.server, player) { - @Override - public void saveData() { - super.saveData(); - // See net.minecraft.server.WorldNBTStorage#save(EntityPlayer) - try { - WorldNBTStorage worldNBTStorage = player.server.getPlayerList().playerFileData; - - NBTTagCompound playerData = player.save(new NBTTagCompound()); - - if (!isOnline()) { - // Special case: save old vehicle data - NBTTagCompound oldData = worldNBTStorage.load(player); - - if (oldData != null && oldData.hasKeyOfType("RootVehicle", 10)) { - // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) - playerData.set("RootVehicle", oldData.getCompound("RootVehicle")); - } - } - - File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat.tmp"); - File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat"); - - NBTCompressedStreamTools.a(playerData, new FileOutputStream(file)); - - if (file1.exists() && !file1.delete() || !file.renameTo(file1)) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); - } - - } catch (Exception e) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); - } - } - }); - } - - @NotNull - @Override - public Player inject(@NotNull Player player) { - try { - EntityPlayer nmsPlayer = getHandle(player); - injectPlayer(nmsPlayer); - return nmsPlayer.getBukkitEntity(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return player; - } - } - - @Nullable - @Override - public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) { - - EntityPlayer nmsPlayer = getHandle(player); - - if (nmsPlayer.playerConnection == null) { - return null; - } - - String title; - if (inventory instanceof SpecialEnderChest) { - HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner(); - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.enderchest", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Ender Chest"; - } - } else if (inventory instanceof SpecialPlayerInventory) { - EntityHuman owner = ((PlayerInventory) inventory).player; - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.player", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Inventory"; - } - } else { - return player.openInventory(inventory.getBukkitInventory()); - } - - String finalTitle = title; - Container container = new CraftContainer(new InventoryView() { - @Override - public @NotNull Inventory getTopInventory() { - return inventory.getBukkitInventory(); - } - @Override - public @NotNull Inventory getBottomInventory() { - return player.getInventory(); - } - @Override - public @NotNull HumanEntity getPlayer() { - return player; - } - @Override - public @NotNull InventoryType getType() { - return inventory.getBukkitInventory().getType(); - } - @Override - public @NotNull String getTitle() { - return finalTitle; - } - }, nmsPlayer, nmsPlayer.nextContainerCounter()) { - @Override - public Containers getType() { - switch (inventory.getBukkitInventory().getSize()) { - case 9: - return Containers.GENERIC_9X1; - case 18: - return Containers.GENERIC_9X2; - case 27: - default: - return Containers.GENERIC_9X3; - case 36: - return Containers.GENERIC_9X4; - case 41: // PLAYER - case 45: - return Containers.GENERIC_9X5; - case 54: - return Containers.GENERIC_9X6; - } - } - }; - - container.setTitle(new ChatComponentText(title)); - container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); - - if (container == null) { - return null; - } - - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), - new ChatComponentText(container.getBukkitView().getTitle()))); - nmsPlayer.activeContainer = container; - container.addSlotListener(nmsPlayer); - - return container.getBukkitView(); - - } - - @Override - public void sendSystemMessage(@NotNull Player player, @NotNull String message) { - int newline = message.indexOf('\n'); - if (newline != -1) { - // No newlines in action bar chat. - message = message.substring(0, newline); - } - - if (message.isEmpty()) { - return; - } - - EntityPlayer nmsPlayer = getHandle(player); - - // For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text. - if (nmsPlayer.playerConnection != null) { - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO, SystemUtils.b)); - } - } - -} diff --git a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialEnderChest.java b/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialEnderChest.java deleted file mode 100644 index f2dc5f6..0000000 --- a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialEnderChest.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_16_R2; - -import com.lishid.openinv.internal.ISpecialEnderChest; -import java.util.List; -import net.minecraft.server.v1_16_R2.AutoRecipeStackManager; -import net.minecraft.server.v1_16_R2.ContainerUtil; -import net.minecraft.server.v1_16_R2.EntityHuman; -import net.minecraft.server.v1_16_R2.EntityPlayer; -import net.minecraft.server.v1_16_R2.IInventoryListener; -import net.minecraft.server.v1_16_R2.InventoryEnderChest; -import net.minecraft.server.v1_16_R2.ItemStack; -import net.minecraft.server.v1_16_R2.NonNullList; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_16_R2.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEnderChest { - - private final CraftInventory inventory; - private EntityPlayer owner; - private NonNullList items; - private boolean playerOnline; - - public SpecialEnderChest(final Player player, final Boolean online) { - super(PlayerDataManager.getHandle(player)); - this.inventory = new CraftInventory(this); - this.owner = PlayerDataManager.getHandle(player); - this.playerOnline = online; - this.items = this.owner.getEnderChest().items; - } - - @Override - public @NotNull CraftInventory getBukkitInventory() { - return inventory; - } - - @Override - public boolean isInUse() { - return !this.getViewers().isEmpty(); - } - - @Override - public void setPlayerOffline() { - this.playerOnline = false; - } - - @Override - public void setPlayerOnline(@NotNull final Player player) { - if (!this.playerOnline) { - try { - this.owner = PlayerDataManager.getHandle(player); - InventoryEnderChest enderChest = owner.getEnderChest(); - for (int i = 0; i < enderChest.getSize(); ++i) { - enderChest.setItem(i, this.items.get(i)); - } - this.items = enderChest.items; - } catch (Exception ignored) {} - this.playerOnline = true; - } - } - - @Override - public void update() { - this.owner.getEnderChest().update(); - } - - @Override - public List getContents() { - return this.items; - } - - @Override - public void onOpen(CraftHumanEntity who) { - this.owner.getEnderChest().onOpen(who); - } - - @Override - public void onClose(CraftHumanEntity who) { - this.owner.getEnderChest().onClose(who); - } - - @Override - public List getViewers() { - return this.owner.getEnderChest().getViewers(); - } - - @Override - public void setMaxStackSize(int i) { - this.owner.getEnderChest().setMaxStackSize(i); - } - - @Override - public InventoryHolder getOwner() { - return this.owner.getEnderChest().getOwner(); - } - - @Override - public @Nullable Location getLocation() { - return null; - } - - @Override - public void a(IInventoryListener iinventorylistener) { - this.owner.getEnderChest().a(iinventorylistener); - } - - @Override - public void b(IInventoryListener iinventorylistener) { - this.owner.getEnderChest().b(iinventorylistener); - } - - @Override - public ItemStack getItem(int i) { - return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.b; - } - - @Override - public ItemStack splitStack(int i, int j) { - ItemStack itemstack = ContainerUtil.a(this.items, i, j); - if (!itemstack.isEmpty()) { - this.update(); - } - - return itemstack; - } - - @Override - public ItemStack a(ItemStack itemstack) { - ItemStack itemstack1 = itemstack.cloneItemStack(); - - for (int i = 0; i < this.getSize(); ++i) { - ItemStack itemstack2 = this.getItem(i); - if (itemstack2.isEmpty()) { - this.setItem(i, itemstack1); - this.update(); - return ItemStack.b; - } - - if (ItemStack.c(itemstack2, itemstack1)) { - int j = Math.min(this.getMaxStackSize(), itemstack2.getMaxStackSize()); - int k = Math.min(itemstack1.getCount(), j - itemstack2.getCount()); - if (k > 0) { - itemstack2.add(k); - itemstack1.subtract(k); - if (itemstack1.isEmpty()) { - this.update(); - return ItemStack.b; - } - } - } - } - - if (itemstack1.getCount() != itemstack.getCount()) { - this.update(); - } - - return itemstack1; - } - - @Override - public ItemStack splitWithoutUpdate(int i) { - ItemStack itemstack = this.items.get(i); - if (itemstack.isEmpty()) { - return ItemStack.b; - } else { - this.items.set(i, ItemStack.b); - return itemstack; - } - } - - @Override - public void setItem(int i, ItemStack itemstack) { - this.items.set(i, itemstack); - if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) { - itemstack.setCount(this.getMaxStackSize()); - } - - this.update(); - } - - @Override - public int getSize() { - return this.owner.getEnderChest().getSize(); - } - - @Override - public boolean isEmpty() { - - for (ItemStack itemstack : this.items) { - if (!itemstack.isEmpty()) { - return false; - } - } - - return true; - } - - @Override - public int getMaxStackSize() { - return 64; - } - - @Override - public boolean a(EntityHuman entityhuman) { - return true; - } - - @Override - public void startOpen(EntityHuman entityhuman) { - } - - @Override - public void closeContainer(EntityHuman entityhuman) { - } - - @Override - public boolean b(int i, ItemStack itemstack) { - return true; - } - - @Override - public void clear() { - this.items.clear(); - } - - @Override - public void a(AutoRecipeStackManager autorecipestackmanager) { - - for (ItemStack itemstack : this.items) { - autorecipestackmanager.b(itemstack); - } - - } - -} diff --git a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialPlayerInventory.java b/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialPlayerInventory.java deleted file mode 100644 index e1b22cf..0000000 --- a/internal/v1_16_R2/src/main/java/com/lishid/openinv/internal/v1_16_R2/SpecialPlayerInventory.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (C) 2011-2020 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_16_R2; - -import com.google.common.collect.ImmutableList; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import net.minecraft.server.v1_16_R2.AutoRecipeStackManager; -import net.minecraft.server.v1_16_R2.ChatMessage; -import net.minecraft.server.v1_16_R2.ContainerUtil; -import net.minecraft.server.v1_16_R2.CrashReport; -import net.minecraft.server.v1_16_R2.CrashReportSystemDetails; -import net.minecraft.server.v1_16_R2.DamageSource; -import net.minecraft.server.v1_16_R2.EntityHuman; -import net.minecraft.server.v1_16_R2.EntityPlayer; -import net.minecraft.server.v1_16_R2.EnumItemSlot; -import net.minecraft.server.v1_16_R2.IBlockData; -import net.minecraft.server.v1_16_R2.IChatBaseComponent; -import net.minecraft.server.v1_16_R2.IInventory; -import net.minecraft.server.v1_16_R2.Item; -import net.minecraft.server.v1_16_R2.ItemArmor; -import net.minecraft.server.v1_16_R2.ItemStack; -import net.minecraft.server.v1_16_R2.NBTTagCompound; -import net.minecraft.server.v1_16_R2.NBTTagList; -import net.minecraft.server.v1_16_R2.NonNullList; -import net.minecraft.server.v1_16_R2.PacketPlayOutSetSlot; -import net.minecraft.server.v1_16_R2.PlayerInventory; -import net.minecraft.server.v1_16_R2.ReportedException; -import net.minecraft.server.v1_16_R2.World; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_16_R2.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { - - private final CraftInventory inventory; - private boolean playerOnline; - private EntityHuman player; - private NonNullList items, armor, extraSlots; - private List> f; - - public SpecialPlayerInventory(final Player bukkitPlayer, final Boolean online) { - super(PlayerDataManager.getHandle(bukkitPlayer)); - this.inventory = new CraftInventory(this); - this.playerOnline = online; - this.player = super.player; - this.items = this.player.inventory.items; - this.armor = this.player.inventory.armor; - this.extraSlots = this.player.inventory.extraSlots; - this.f = ImmutableList.of(this.items, this.armor, this.extraSlots); - } - - @Override - public void setPlayerOnline(@NotNull final Player player) { - if (!this.playerOnline) { - EntityPlayer entityPlayer = PlayerDataManager.getHandle(player); - entityPlayer.inventory.transaction.addAll(this.transaction); - this.player = entityPlayer; - for (int i = 0; i < getSize(); ++i) { - this.player.inventory.setItem(i, getRawItem(i)); - } - this.player.inventory.itemInHandIndex = this.itemInHandIndex; - this.items = this.player.inventory.items; - this.armor = this.player.inventory.armor; - this.extraSlots = this.player.inventory.extraSlots; - this.f = ImmutableList.of(this.items, this.armor, this.extraSlots); - this.playerOnline = true; - } - } - - @Override - public boolean a(final EntityHuman entityhuman) { - return true; - } - - @Override - public @NotNull CraftInventory getBukkitInventory() { - return this.inventory; - } - - @Override - public ItemStack getItem(int i) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.b; - } - - return list.get(i); - } - - private ItemStack getRawItem(int i) { - NonNullList list = null; - for (NonNullList next : this.f) { - if (i < next.size()) { - list = next; - break; - } - i -= next.size(); - } - - return list == null ? ItemStack.b : list.get(i); - } - - @Override - public IChatBaseComponent getDisplayName() { - return new ChatMessage(this.player.getName()); - } - - @Override - public boolean hasCustomName() { - return false; - } - - private int getReversedArmorSlotNum(final int i) { - if (i == 0) { - return 3; - } - if (i == 1) { - return 2; - } - if (i == 2) { - return 1; - } - if (i == 3) { - return 0; - } - return i; - } - - private int getReversedItemSlotNum(final int i) { - if (i >= 27) { - return i - 27; - } - return i + 9; - } - - @Override - public int getSize() { - return 45; - } - - @Override - public boolean isInUse() { - return !this.getViewers().isEmpty(); - } - - @Override - public void setItem(int i, final ItemStack itemstack) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - this.player.drop(itemstack, true); - return; - } - - list.set(i, itemstack); - } - - @Override - public void setPlayerOffline() { - this.playerOnline = false; - } - - @Override - public ItemStack splitStack(int i, final int j) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.b; - } - - return list.get(i).isEmpty() ? ItemStack.b : ContainerUtil.a(list, i, j); - } - - @Override - public ItemStack splitWithoutUpdate(int i) { - List list = this.items; - - if (i >= list.size()) { - i -= list.size(); - list = this.armor; - } else { - i = this.getReversedItemSlotNum(i); - } - - if (i >= list.size()) { - i -= list.size(); - list = this.extraSlots; - } else if (list == this.armor) { - i = this.getReversedArmorSlotNum(i); - } - - if (i >= list.size()) { - return ItemStack.b; - } - - if (!list.get(i).isEmpty()) { - ItemStack itemstack = list.get(i); - - list.set(i, ItemStack.b); - return itemstack; - } - - return ItemStack.b; - } - - @Override - public List getContents() { - return this.f.stream().flatMap(List::stream).collect(Collectors.toList()); - } - - @Override - public List getArmorContents() { - return this.armor; - } - - @Override - public void onOpen(CraftHumanEntity who) { - this.transaction.add(who); - } - - @Override - public void onClose(CraftHumanEntity who) { - this.transaction.remove(who); - } - - @Override - public List getViewers() { - return this.transaction; - } - - @Override - public InventoryHolder getOwner() { - return this.player.getBukkitEntity(); - } - - @Override - public Location getLocation() { - return this.player.getBukkitEntity().getLocation(); - } - - @Override - public ItemStack getItemInHand() { - return d(this.itemInHandIndex) ? this.items.get(this.itemInHandIndex) : ItemStack.b; - } - - private boolean isSimilarAndNotFull(ItemStack itemstack, ItemStack itemstack1) { - return !itemstack.isEmpty() && this.b(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize(); - } - - private boolean b(ItemStack itemstack, ItemStack itemstack1) { - return itemstack.getItem() == itemstack1.getItem() && ItemStack.equals(itemstack, itemstack1); - } - - @Override - public int canHold(ItemStack itemstack) { - int remains = itemstack.getCount(); - - for (int i = 0; i < this.items.size(); ++i) { - ItemStack itemstack1 = this.getItem(i); - if (itemstack1.isEmpty()) { - return itemstack.getCount(); - } - - if (!this.isSimilarAndNotFull(itemstack, itemstack1)) { - remains -= Math.min(itemstack1.getMaxStackSize(), this.getMaxStackSize()) - itemstack1.getCount(); - } - - if (remains <= 0) { - return itemstack.getCount(); - } - } - - ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); - if (this.isSimilarAndNotFull(offhandItemStack, itemstack)) { - remains -= Math.min(offhandItemStack.getMaxStackSize(), this.getMaxStackSize()) - offhandItemStack.getCount(); - } - - return itemstack.getCount() - remains; - } - - @Override - public int getFirstEmptySlotIndex() { - for (int i = 0; i < this.items.size(); ++i) { - if (this.items.get(i).isEmpty()) { - return i; - } - } - - return -1; - } - - @Override - public void c(int i) { - this.itemInHandIndex = this.i(); - ItemStack itemstack = this.items.get(this.itemInHandIndex); - this.items.set(this.itemInHandIndex, this.items.get(i)); - this.items.set(i, itemstack); - } - - @Override - public int c(ItemStack itemstack) { - for (int i = 0; i < this.items.size(); ++i) { - ItemStack itemstack1 = this.items.get(i); - if (!this.items.get(i).isEmpty() && this.b(itemstack, this.items.get(i)) && !this.items.get(i).f() && !itemstack1.hasEnchantments() && !itemstack1.hasName()) { - return i; - } - } - - return -1; - } - - @Override - public int i() { - int i; - int j; - for (j = 0; j < 9; ++j) { - i = (this.itemInHandIndex + j) % 9; - if (this.items.get(i).isEmpty()) { - return i; - } - } - - for (j = 0; j < 9; ++j) { - i = (this.itemInHandIndex + j) % 9; - if (!this.items.get(i).hasEnchantments()) { - return i; - } - } - - return this.itemInHandIndex; - } - - @Override - public int a(Predicate predicate, int i, IInventory iinventory) { - byte b0 = 0; - boolean flag = i == 0; - int j = b0 + ContainerUtil.a(this, predicate, i - b0, flag); - j += ContainerUtil.a(iinventory, predicate, i - j, flag); - j += ContainerUtil.a(this.getCarried(), predicate, i - j, flag); - if (this.getCarried().isEmpty()) { - this.setCarried(ItemStack.b); - } - - return j; - } - - private int i(ItemStack itemstack) { - int i = this.firstPartial(itemstack); - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - return i == -1 ? itemstack.getCount() : this.d(i, itemstack); - } - - private int d(int i, ItemStack itemstack) { - Item item = itemstack.getItem(); - int j = itemstack.getCount(); - ItemStack itemstack1 = this.getItem(i); - if (itemstack1.isEmpty()) { - itemstack1 = new ItemStack(item, 0); - NBTTagCompound tag = itemstack.getTag(); - if (tag != null) { - itemstack1.setTag(tag.clone()); - } - - this.setItem(i, itemstack1); - } - - int k = j; - if (j > itemstack1.getMaxStackSize() - itemstack1.getCount()) { - k = itemstack1.getMaxStackSize() - itemstack1.getCount(); - } - - if (k > this.getMaxStackSize() - itemstack1.getCount()) { - k = this.getMaxStackSize() - itemstack1.getCount(); - } - - if (k != 0) { - j -= k; - itemstack1.add(k); - itemstack1.d(5); - } - return j; - } - - @Override - public int firstPartial(ItemStack itemstack) { - if (this.isSimilarAndNotFull(this.getItem(this.itemInHandIndex), itemstack)) { - return this.itemInHandIndex; - } else if (this.isSimilarAndNotFull(this.getItem(40), itemstack)) { - return 40; - } else { - for (int i = 0; i < this.items.size(); ++i) { - if (this.isSimilarAndNotFull(this.items.get(i), itemstack)) { - return i; - } - } - - return -1; - } - } - - @Override - public void j() { - - for (List itemStacks : this.f) { - for (int i = 0; i < itemStacks.size(); ++i) { - if (!itemStacks.get(i).isEmpty()) { - itemStacks.get(i).a(this.player.world, this.player, i, this.itemInHandIndex == i); - } - } - } - - } - - @Override - public boolean pickup(ItemStack itemstack) { - return this.c(-1, itemstack); - } - - @Override - public boolean c(int i, ItemStack itemstack) { - if (itemstack.isEmpty()) { - return false; - } else { - try { - if (itemstack.f()) { - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - if (i >= 0) { - this.items.set(i, itemstack.cloneItemStack()); - this.items.get(i).d(5); - itemstack.setCount(0); - return true; - } else if (this.player.abilities.canInstantlyBuild) { - itemstack.setCount(0); - return true; - } else { - return false; - } - } else { - int j; - do { - j = itemstack.getCount(); - if (i == -1) { - itemstack.setCount(this.i(itemstack)); - } else { - itemstack.setCount(this.d(i, itemstack)); - } - } while(!itemstack.isEmpty() && itemstack.getCount() < j); - - if (itemstack.getCount() == j && this.player.abilities.canInstantlyBuild) { - itemstack.setCount(0); - return true; - } else { - return itemstack.getCount() < j; - } - } - } catch (Throwable var6) { - CrashReport crashreport = CrashReport.a(var6, "Adding item to inventory"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Item being added"); - crashreportsystemdetails.a("Item ID", Item.getId(itemstack.getItem())); - crashreportsystemdetails.a("Item data", itemstack.getDamage()); - crashreportsystemdetails.a("Item name", () -> itemstack.getName().getString()); - throw new ReportedException(crashreport); - } - } - } - - @Override - public void a(World world, ItemStack itemstack) { - if (!world.isClientSide) { - while(!itemstack.isEmpty()) { - int i = this.firstPartial(itemstack); - if (i == -1) { - i = this.getFirstEmptySlotIndex(); - } - - if (i == -1) { - this.player.drop(itemstack, false); - break; - } - - int j = itemstack.getMaxStackSize() - this.getItem(i).getCount(); - if (this.c(i, itemstack.cloneAndSubtract(j))) { - ((EntityPlayer)this.player).playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, i, this.getItem(i))); - } - } - } - - } - - @Override - public void f(ItemStack itemstack) { - - for (List list : this.f) { - for (int i = 0; i < list.size(); ++i) { - if (list.get(i) == itemstack) { - list.set(i, ItemStack.b); - break; - } - } - } - } - - @Override - public float a(IBlockData iblockdata) { - return this.items.get(this.itemInHandIndex).a(iblockdata); - } - - @Override - public NBTTagList a(NBTTagList nbttaglist) { - NBTTagCompound nbttagcompound; - int i; - for (i = 0; i < this.items.size(); ++i) { - if (!this.items.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) i); - this.items.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - for (i = 0; i < this.armor.size(); ++i) { - if (!this.armor.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) (i + 100)); - this.armor.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - for (i = 0; i < this.extraSlots.size(); ++i) { - if (!this.extraSlots.get(i).isEmpty()) { - nbttagcompound = new NBTTagCompound(); - nbttagcompound.setByte("Slot", (byte) (i + 150)); - this.extraSlots.get(i).save(nbttagcompound); - nbttaglist.add(nbttagcompound); - } - } - - return nbttaglist; - } - - @Override - public void b(NBTTagList nbttaglist) { - this.items.clear(); - this.armor.clear(); - this.extraSlots.clear(); - - for(int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound = nbttaglist.getCompound(i); - int j = nbttagcompound.getByte("Slot") & 255; - ItemStack itemstack = ItemStack.a(nbttagcompound); - if (!itemstack.isEmpty()) { - if (j < this.items.size()) { - this.items.set(j, itemstack); - } else if (j >= 100 && j < this.armor.size() + 100) { - this.armor.set(j - 100, itemstack); - } else if (j >= 150 && j < this.extraSlots.size() + 150) { - this.extraSlots.set(j - 150, itemstack); - } - } - } - - } - - @Override - public boolean isEmpty() { - Iterator iterator = this.items.iterator(); - - ItemStack itemstack; - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - iterator = this.armor.iterator(); - - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - iterator = this.extraSlots.iterator(); - - while (iterator.hasNext()) { - itemstack = iterator.next(); - if (!itemstack.isEmpty()) { - return false; - } - } - - return true; - } - - @Nullable - @Override - public IChatBaseComponent getCustomName() { - return null; - } - - @Override - public void a(DamageSource damagesource, float f) { - if (f > 0.0F) { - f /= 4.0F; - if (f < 1.0F) { - f = 1.0F; - } - - for (int i = 0; i < this.armor.size(); ++i) { - ItemStack itemstack = this.armor.get(0); - int index = i; - if ((!damagesource.isFire() || !itemstack.getItem().u()) && itemstack.getItem() instanceof ItemArmor) { - itemstack.damage((int) f, this.player, (entityHuman) -> entityHuman.broadcastItemBreak(EnumItemSlot.a(EnumItemSlot.Function.ARMOR, index))); - } - } - } - } - - @Override - public void dropContents() { - for (List itemStacks : this.f) { - for (int i = 0; i < itemStacks.size(); ++i) { - ItemStack itemstack = itemStacks.get(i); - if (!itemstack.isEmpty()) { - itemStacks.set(i, ItemStack.b); - this.player.a(itemstack, true, false); - } - } - } - } - - @Override - public boolean h(ItemStack itemstack) { - return this.f.stream().flatMap(List::stream).anyMatch(itemStack1 -> !itemStack1.isEmpty() && itemStack1.doMaterialsMatch(itemstack)); - } - - @Override - public void a(PlayerInventory playerinventory) { - for (int i = 0; i < playerinventory.getSize(); ++i) { - this.setItem(i, playerinventory.getItem(i)); - } - - this.itemInHandIndex = playerinventory.itemInHandIndex; - } - - @Override - public void clear() { - this.f.forEach(List::clear); - } - - @Override - public void a(AutoRecipeStackManager autorecipestackmanager) { - for (ItemStack itemstack : this.items) { - autorecipestackmanager.a(itemstack); - } - } - -} diff --git a/internal/v1_8_R3/pom.xml b/internal/v1_8_R3/pom.xml deleted file mode 100644 index 6c77d0e..0000000 --- a/internal/v1_8_R3/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.6-SNAPSHOT - - - openinvadapter1_8_R3 - OpenInvAdapter1_8_R3 - - - - org.spigotmc - spigot - 1.8.8-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.6-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.2 - - true - - - - package - - shade - - - - - - - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - - diff --git a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java deleted file mode 100644 index e671037..0000000 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2011-2020 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 java.lang.reflect.Field; -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.ITileInventory; -import net.minecraft.server.v1_8_R3.InventoryEnderChest; -import net.minecraft.server.v1_8_R3.InventoryLargeChest; -import net.minecraft.server.v1_8_R3.PlayerInteractManager; -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 net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; - -public class AnySilentContainer implements IAnySilentContainer { - - private Field playerInteractManagerGamemode; - - public AnySilentContainer() { - try { - this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); - this.playerInteractManagerGamemode.setAccessible(true); - } catch (Exception e) { - System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); - e.printStackTrace(); - } - } - - @Override - public boolean isAnySilentContainer(@NotNull org.bukkit.block.Block bukkitBlock) { - return bukkitBlock.getType() == Material.ENDER_CHEST || bukkitBlock.getState() instanceof org.bukkit.block.Chest; - } - - @Override - public boolean isAnyContainerNeeded(@NotNull Player bukkitPlayer, @NotNull org.bukkit.block.Block bukkitBlock) { - - World world = PlayerDataManager.getHandle(bukkitPlayer).world; - BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.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(@NotNull Player bukkitPlayer, boolean silent, @NotNull org.bukkit.block.Block bukkitBlock) { - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - // Silent ender chest is pretty much API-only - if (silent && bukkitBlock.getType() == Material.ENDER_CHEST) { - bukkitPlayer.openInventory(bukkitPlayer.getEnderChest()); - player.b(StatisticList.V); - return true; - } - - World world = player.world; - BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.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 ITileInventory)) { - return false; - } - - ITileInventory tileInventory = (ITileInventory) tile; - 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)) { - tileInventory = new InventoryLargeChest("container.chestDouble", - (TileEntityChest) localTileEntity, tileInventory); - } else { - tileInventory = new InventoryLargeChest("container.chestDouble", - tileInventory, (TileEntityChest) localTileEntity); - } - break; - } - - BlockChest blockChest = (BlockChest) block; - if (blockChest.b == 0) { - player.b(StatisticList.aa); - } else if (blockChest.b == 1) { - player.b(StatisticList.U); - } - } - - // AnyChest only - SilentChest not active, container unsupported, or unnecessary. - if (!silent || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { - player.openContainer(tileInventory); - return true; - } - - // SilentChest requires access to setting players' gamemode directly. - if (this.playerInteractManagerGamemode == null) { - return false; - } - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.openContainer(tileInventory); - this.forceGameMode(player, gamemode); - return true; - } - - @Override - public void deactivateContainer(@NotNull final Player bukkitPlayer) { - if (this.playerInteractManagerGamemode == null) { - return; - } - - InventoryView view = bukkitPlayer.getOpenInventory(); - switch (view.getType()) { - case CHEST: - case ENDER_CHEST: - break; - default: - return; - } - - EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); - - EnumGamemode gamemode = player.playerInteractManager.getGameMode(); - this.forceGameMode(player, EnumGamemode.SPECTATOR); - player.activeContainer.b(player); - player.activeContainer.a(player, false); - player.activeContainer.transferTo(player.defaultContainer, player.getBukkitEntity()); - player.activeContainer = player.defaultContainer; - this.forceGameMode(player, gamemode); - } - - private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { - if (this.playerInteractManagerGamemode == null) { - // No need to warn repeatedly, error on startup and lack of function should be enough. - return; - } - try { - if (!this.playerInteractManagerGamemode.isAccessible()) { - // Just in case, ensure accessible. - this.playerInteractManagerGamemode.setAccessible(true); - } - this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); - } catch (Exception e) { - e.printStackTrace(); - } - } - -} diff --git a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java deleted file mode 100644 index f38240d..0000000 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/PlayerDataManager.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2011-2020 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.lishid.openinv.internal.ISpecialInventory; -import com.mojang.authlib.GameProfile; -import java.io.File; -import java.io.FileOutputStream; -import java.lang.reflect.Field; -import net.minecraft.server.v1_8_R3.ChatComponentText; -import net.minecraft.server.v1_8_R3.Entity; -import net.minecraft.server.v1_8_R3.EntityPlayer; -import net.minecraft.server.v1_8_R3.MinecraftServer; -import net.minecraft.server.v1_8_R3.NBTCompressedStreamTools; -import net.minecraft.server.v1_8_R3.NBTTagCompound; -import net.minecraft.server.v1_8_R3.PacketPlayOutChat; -import net.minecraft.server.v1_8_R3.PlayerInteractManager; -import net.minecraft.server.v1_8_R3.WorldNBTStorage; -import org.apache.logging.log4j.LogManager; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.Server; -import org.bukkit.craftbukkit.v1_8_R3.CraftServer; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class PlayerDataManager implements IPlayerDataManager { - - private Field bukkitEntity; - - public PlayerDataManager() { - try { - bukkitEntity = Entity.class.getDeclaredField("bukkitEntity"); - } catch (NoSuchFieldException e) { - System.out.println("Unable to obtain field to inject custom save process - players' mounts may be deleted when loaded."); - e.printStackTrace(); - bukkitEntity = null; - } - } - - @NotNull - public static EntityPlayer getHandle(Player player) { - if (player instanceof CraftPlayer) { - return ((CraftPlayer) player).getHandle(); - } - - Server server = player.getServer(); - EntityPlayer nmsPlayer = null; - - if (server instanceof CraftServer) { - nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName()); - } - - if (nmsPlayer == null) { - // Could use reflection to examine fields, but it's honestly not worth the bother. - throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation"); - } - - return nmsPlayer; - } - - @Nullable - @Override - public Player loadPlayer(@NotNull OfflinePlayer offline) { - // Ensure the player has data - if (!offline.hasPlayedBefore()) { - return null; - } - - // Create a profile and entity to load the player data - GameProfile profile = new GameProfile(offline.getUniqueId(), - offline.getName() != null ? offline.getName() : offline.getUniqueId().toString()); - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, - new PlayerInteractManager(server.getWorldServer(0))); - - try { - injectPlayer(entity); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - // Get the bukkit entity - Player target = entity.getBukkitEntity(); - if (target != null) { - // Load data - target.loadData(); - } - // Return the entity - return target; - } - - void injectPlayer(EntityPlayer player) throws IllegalAccessException { - if (bukkitEntity == null) { - return; - } - - bukkitEntity.setAccessible(true); - - bukkitEntity.set(player, new CraftPlayer(player.server.server, player) { - @Override - public void saveData() { - super.saveData(); - // See net.minecraft.server.WorldNBTStorage#save(EntityHuman) - try { - WorldNBTStorage worldNBTStorage = (WorldNBTStorage) player.server.getPlayerList().playerFileData; - - NBTTagCompound playerData = new NBTTagCompound(); - player.e(playerData); - - if (!isOnline()) { - // Special case: save old vehicle data - NBTTagCompound oldData = worldNBTStorage.load(player); - - if (oldData != null && oldData.hasKeyOfType("Riding", 10)) { - // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) - playerData.set("Riding", oldData.getCompound("Riding")); - } - } - - File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueID().toString() + ".dat.tmp"); - File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueID().toString() + ".dat"); - - NBTCompressedStreamTools.a(playerData, new FileOutputStream(file)); - - if (file1.exists()) { - file1.delete(); - } - - file.renameTo(file1); - } catch (Exception e) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getName()); - } - } - }); - } - - @NotNull - @Override - public Player inject(@NotNull Player player) { - try { - EntityPlayer nmsPlayer = getHandle(player); - injectPlayer(nmsPlayer); - return nmsPlayer.getBukkitEntity(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return player; - } - } - - @Nullable - @Override - public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) { - return player.openInventory(inventory.getBukkitInventory()); - } - - @Override - public void sendSystemMessage(@NotNull Player player, @NotNull String message) { - int newline = message.indexOf('\n'); - if (newline != -1) { - // No newlines in action bar chat. - message = message.substring(0, newline); - } - - if (message.isEmpty()) { - return; - } - - EntityPlayer nmsPlayer = getHandle(player); - - // For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text. - if (nmsPlayer.playerConnection != null) { - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), (byte) 2)); - } - } - - @NotNull - @Override - public String getLocale(Player player) { - return getHandle(player).locale; - } - -} diff --git a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java deleted file mode 100644 index dda4e17..0000000 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialEnderChest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011-2020 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.ISpecialEnderChest; -import java.lang.reflect.Field; -import net.minecraft.server.v1_8_R3.EntityPlayer; -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.inventory.CraftInventory; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; - -public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { - - private final InventoryEnderChest enderChest; - private final CraftInventory inventory = new CraftInventory(this); - private boolean playerOnline; - - public SpecialEnderChest(Player player, Boolean online) { - super(PlayerDataManager.getHandle(player).getEnderChest().getName(), - PlayerDataManager.getHandle(player).getEnderChest().hasCustomName(), - PlayerDataManager.getHandle(player).getEnderChest().getSize()); - this.playerOnline = online; - EntityPlayer nmsPlayer = PlayerDataManager.getHandle(player); - this.enderChest = nmsPlayer.getEnderChest(); - this.bukkitOwner = nmsPlayer.getBukkitEntity(); - this.items = enderChest.getContents(); - } - - @Override - public @NotNull Inventory getBukkitInventory() { - return inventory; - } - - @Override - public void setPlayerOnline(@NotNull Player player) { - if (!playerOnline) { - try { - EntityPlayer nmsPlayer = PlayerDataManager.getHandle(player); - this.bukkitOwner = nmsPlayer.getBukkitEntity(); - InventoryEnderChest playerEnderChest = nmsPlayer.getEnderChest(); - Field field = playerEnderChest.getClass().getField("items"); - field.setAccessible(true); - field.set(playerEnderChest, this.items); - } catch (Exception ignored) {} - 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/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java deleted file mode 100644 index 46f0a3b..0000000 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SpecialPlayerInventory.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2011-2020 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 net.minecraft.server.v1_8_R3.ItemStack; -import net.minecraft.server.v1_8_R3.PlayerInventory; -import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; - -public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { - - private final ItemStack[] extra = new ItemStack[5]; - private final CraftInventory inventory = new CraftInventory(this); - private boolean playerOnline; - - public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { - super(PlayerDataManager.getHandle(bukkitPlayer)); - this.playerOnline = online; - this.items = player.inventory.items; - this.armor = player.inventory.armor; - } - - @Override - public @NotNull Inventory getBukkitInventory() { - return inventory; - } - - @Override - public void setPlayerOnline(@NotNull Player player) { - if (!playerOnline) { - this.player = PlayerDataManager.getHandle(player); - 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(); - } - - @Override - public boolean hasCustomName() { - return true; - } - -} diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index 96f3b7b..fb24552 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -81,6 +81,7 @@ public class InternalAccessor { case "v1_8_R3": case "v1_15_R1": case "v1_16_R2": + return "https://github.com/lishid/OpenInv/releases/tag/4.1.5"; case "v1_16_R3": default: return "https://github.com/lishid/OpenInv/releases"; diff --git a/plugin/src/main/resources/plugin.yml b/plugin/src/main/resources/plugin.yml index ce43adb..767b886 100644 --- a/plugin/src/main/resources/plugin.yml +++ b/plugin/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ author: lishid authors: [Jikoo, ShadowRanger] description: > This plugin allows you to open a player's inventory as a chest and interact with it in real time. -api-version: "1.15" +api-version: "1.16" permissions: OpenInv.any.default: From 519dd7da333228fc3de9709b79cd048a2c533fb3 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Tue, 16 Mar 2021 09:45:04 -0400 Subject: [PATCH 2/8] Fix cache breaking build on Spigot version change --- .github/workflows/ci.yml | 13 ++--- internal/v1_16_R3/pom.xml | 2 +- scripts/install_spigot_dependencies.sh | 75 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 scripts/install_spigot_dependencies.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 932d513..e65f0f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,8 +9,6 @@ on: jobs: build: runs-on: ubuntu-latest - strategy: - fail-fast: true steps: - name: Checkout Code uses: actions/checkout@v2 @@ -28,15 +26,10 @@ jobs: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - # If the cache was not present, run BuildTools to install the relevant versions to Maven. - # This will take approximately forever. + # Install Spigot dependencies. + # This script uses Maven to check all required installations and ensure that they are present. - name: Install Spigot Dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: | - mkdir ~/buildtools - cd ~/buildtools - wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar - java -jar BuildTools.jar --rev 1.16.4 + run: . scripts/install_spigot_dependencies.sh - name: Build With Maven run: mvn -e clean package -am -P all diff --git a/internal/v1_16_R3/pom.xml b/internal/v1_16_R3/pom.xml index d7998c9..74905ed 100644 --- a/internal/v1_16_R3/pom.xml +++ b/internal/v1_16_R3/pom.xml @@ -32,7 +32,7 @@ org.spigotmc spigot - 1.16.4-R0.1-SNAPSHOT + 1.16.5-R0.1-SNAPSHOT provided diff --git a/scripts/install_spigot_dependencies.sh b/scripts/install_spigot_dependencies.sh new file mode 100644 index 0000000..09e93e1 --- /dev/null +++ b/scripts/install_spigot_dependencies.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# +# Copyright (C) 2011-2021 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 . +# + +# A script for installing required Spigot versions. +# +# Note that this script is designed for use in GitHub Actions, and is +# not particularly robust nor configurable. +# In its current state, the script must be run from OpenInv's parent +# project directory and will always install BuildTools to ~/buildtools. + +buildtools_dir=~/buildtools +buildtools=$buildtools_dir/BuildTools.jar + +get_spigot_versions () { + # Get all submodules of internal module + modules=$(mvn help:evaluate -Dexpression=project.modules -q -DforceStdout -P all -pl internal | grep -oP '(?<=)(.*)(?=<\/string>)') + for module in "${modules[@]}"; do + + # Get number of dependencies declared in pom of specified internal module + max_index=$(mvn help:evaluate -Dexpression=project.dependencies -q -DforceStdout -P all -pl internal/"$module" | grep -c "") + + for ((i=0; i < max_index; i++)); do + # Get artifactId of dependency + artifact_id=$(mvn help:evaluate -Dexpression=project.dependencies["$i"].artifactId -q -DforceStdout -P all -pl internal/"$module") + + # Ensure dependency is spigot + if [[ "$artifact_id" == spigot ]]; then + # Get spigot version + spigot_version=$(mvn help:evaluate -Dexpression=project.dependencies["$i"].version -q -DforceStdout -P all -pl internal/"$module") + echo "$spigot_version" + break + fi + done + done +} + +get_buildtools () { + if [[ -d $buildtools_dir && -f $buildtools ]]; then + return + fi + + mkdir $buildtools_dir + wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar -O $buildtools +} + +versions=$(get_spigot_versions) +echo Found Spigot dependencies: "$versions" + +for version in "${versions[@]}"; do + set -e + exit_code=0 + mvn dependency:get -Dartifact=org.spigotmc:spigot:"$version" -q -o || exit_code=$? + if [ $exit_code -ne 0 ]; then + echo Installing missing Spigot version "$version" + revision=$(echo "$version" | grep -oP '(\d+\.\d+(\.\d+)?)(?=-R[0-9\.]+-SNAPSHOT)') + get_buildtools + java -jar $buildtools -rev "$revision" + else + echo Spigot "$version" is already installed + fi +done From dad1e16c188f51f4ca193094e9d76cd91da319bb Mon Sep 17 00:00:00 2001 From: Jikoo Date: Tue, 16 Mar 2021 11:59:07 -0400 Subject: [PATCH 3/8] Fix item dupe in own inventory Reduce desync for other actions in own inventory Closes #182 --- .../openinv/listeners/InventoryListener.java | 91 +++++++++++++++---- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java b/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java index 33221f2..676635a 100644 --- a/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java +++ b/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java @@ -16,7 +16,8 @@ package com.lishid.openinv.listeners; -import com.lishid.openinv.IOpenInv; +import com.lishid.openinv.OpenInv; +import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.util.InventoryAccess; import com.lishid.openinv.util.Permissions; import org.bukkit.GameMode; @@ -25,11 +26,14 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryInteractEvent; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; /** * Listener for inventory-related events to prevent modification of inventories where not allowed. @@ -38,14 +42,14 @@ import org.bukkit.inventory.Inventory; */ public class InventoryListener implements Listener { - private final IOpenInv plugin; + private final OpenInv plugin; - public InventoryListener(final IOpenInv plugin) { + public InventoryListener(final OpenInv plugin) { this.plugin = plugin; } @EventHandler - public void onInventoryClose(final InventoryCloseEvent event) { + public void onInventoryClose(@NotNull final InventoryCloseEvent event) { if (!(event.getPlayer() instanceof Player)) { return; } @@ -58,37 +62,92 @@ public class InventoryListener implements Listener { } @EventHandler(priority = EventPriority.LOWEST) - public void onInventoryClick(InventoryClickEvent event) { - onInventoryInteract(event); + public void onInventoryClick(@NotNull final InventoryClickEvent event) { + if (handleInventoryInteract(event)) { + return; + } + + // Only specially handle actions in the player's own inventory. + if (!event.getWhoClicked().equals(event.getView().getTopInventory().getHolder())) { + return; + } + + // Safe cast - has to be a player to be the holder of a special player inventory. + Player player = (Player) event.getWhoClicked(); + + if (event.getAction() != InventoryAction.MOVE_TO_OTHER_INVENTORY) { + // All own-inventory interactions require updates to display properly. + // Update in same tick after event completion. + this.plugin.getServer().getScheduler().runTask(this.plugin, player::updateInventory); + return; + } + + // Extra handling for MOVE_TO_OTHER_INVENTORY - apparently Mojang no longer removes the item from the target + // inventory prior to adding it to existing stacks. + ItemStack currentItem = event.getCurrentItem(); + if (currentItem == null) { + // Other plugin doing some sort of handling (would be NOTHING for null item otherwise), ignore. + return; + } + + ItemStack clone = currentItem.clone(); + event.setCurrentItem(null); + + // Complete add action in same tick after event completion. + this.plugin.getServer().getScheduler().runTask(this.plugin, () -> { + player.getInventory().addItem(clone); + player.updateInventory(); + }); } @EventHandler(priority = EventPriority.LOWEST) - public void onInventoryDrag(InventoryDragEvent event) { - onInventoryInteract(event); + public void onInventoryDrag(@NotNull final InventoryDragEvent event) { + handleInventoryInteract(event); } - private void onInventoryInteract(InventoryInteractEvent event) { + /** + * Handle common InventoryInteractEvent functions. + * + * @param event the InventoryInteractEvent + * @return true unless the top inventory is an opened player inventory + */ + private boolean handleInventoryInteract(@NotNull final InventoryInteractEvent event) { HumanEntity entity = event.getWhoClicked(); + // Un-cancel spectator interactions. if (Permissions.SPECTATE.hasPermission(entity) && entity.getGameMode() == GameMode.SPECTATOR) { event.setCancelled(false); } if (event.isCancelled()) { - return; + return true; } - Inventory inventory = event.getInventory(); + Inventory inventory = event.getView().getTopInventory(); - if (InventoryAccess.isPlayerInventory(inventory)) { - if (!Permissions.EDITINV.hasPermission(entity)) { - event.setCancelled(true); - } - } else if (InventoryAccess.isEnderChest(inventory)) { + // Is the inventory a special ender chest? + if (InventoryAccess.isEnderChest(inventory)) { + // Disallow ender chest interaction for users without edit permission. if (!Permissions.EDITENDER.hasPermission(entity)) { event.setCancelled(true); } + return true; } + + ISpecialPlayerInventory playerInventory = InventoryAccess.getPlayerInventory(inventory); + + // Ignore inventories other than special player inventories. + if (playerInventory == null) { + return true; + } + + // Disallow player inventory interaction for users without edit permission. + if (!Permissions.EDITINV.hasPermission(entity)) { + event.setCancelled(true); + return true; + } + + return false; } } From 1c9d133ed1e0865c03edab477aa5899112d8c5c7 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Tue, 16 Mar 2021 23:49:10 -0400 Subject: [PATCH 4/8] Fix item delete in own inventory Dragging items across top and bottom inventories with own inventory open resulted in the overlapping content being deleted. --- .../internal/v1_16_R3/PlayerDataManager.java | 124 +++++++++--------- .../main/java/com/lishid/openinv/OpenInv.java | 14 ++ .../openinv/internal/IPlayerDataManager.java | 12 ++ .../openinv/internal/OpenInventoryView.java | 83 ++++++++++++ .../openinv/listeners/InventoryListener.java | 68 ++++++++-- 5 files changed, 233 insertions(+), 68 deletions(-) create mode 100644 plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java index e0737c5..4c029db 100644 --- a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java @@ -16,9 +16,9 @@ package com.lishid.openinv.internal.v1_16_R3; -import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; import java.io.File; import java.io.FileOutputStream; @@ -28,7 +28,6 @@ import net.minecraft.server.v1_16_R3.ChatMessageType; import net.minecraft.server.v1_16_R3.Container; import net.minecraft.server.v1_16_R3.Containers; import net.minecraft.server.v1_16_R3.Entity; -import net.minecraft.server.v1_16_R3.EntityHuman; import net.minecraft.server.v1_16_R3.EntityPlayer; import net.minecraft.server.v1_16_R3.MinecraftServer; import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools; @@ -36,7 +35,6 @@ import net.minecraft.server.v1_16_R3.NBTTagCompound; import net.minecraft.server.v1_16_R3.PacketPlayOutChat; import net.minecraft.server.v1_16_R3.PacketPlayOutOpenWindow; import net.minecraft.server.v1_16_R3.PlayerInteractManager; -import net.minecraft.server.v1_16_R3.PlayerInventory; import net.minecraft.server.v1_16_R3.SystemUtils; import net.minecraft.server.v1_16_R3.World; import net.minecraft.server.v1_16_R3.WorldNBTStorage; @@ -49,10 +47,7 @@ import org.bukkit.craftbukkit.v1_16_R3.CraftServer; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftContainer; -import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -195,68 +190,20 @@ public class PlayerDataManager implements IPlayerDataManager { return null; } - String title; - if (inventory instanceof SpecialEnderChest) { - HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner(); - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.enderchest", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Ender Chest"; - } - } else if (inventory instanceof SpecialPlayerInventory) { - EntityHuman owner = ((PlayerInventory) inventory).player; - title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.player", "%player%", owner.getName()); - if (title == null) { - title = owner.getName() + "'s Inventory"; - } - } else { + InventoryView view = getView(player, inventory); + + if (view == null) { return player.openInventory(inventory.getBukkitInventory()); } - String finalTitle = title; - Container container = new CraftContainer(new InventoryView() { - @Override - public @NotNull Inventory getTopInventory() { - return inventory.getBukkitInventory(); - } - @Override - public @NotNull Inventory getBottomInventory() { - return player.getInventory(); - } - @Override - public @NotNull HumanEntity getPlayer() { - return player; - } - @Override - public @NotNull InventoryType getType() { - return inventory.getBukkitInventory().getType(); - } - @Override - public @NotNull String getTitle() { - return finalTitle; - } - }, nmsPlayer, nmsPlayer.nextContainerCounter()) { + Container container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) { @Override public Containers getType() { - switch (inventory.getBukkitInventory().getSize()) { - case 9: - return Containers.GENERIC_9X1; - case 18: - return Containers.GENERIC_9X2; - case 27: - default: - return Containers.GENERIC_9X3; - case 36: - return Containers.GENERIC_9X4; - case 41: // PLAYER - case 45: - return Containers.GENERIC_9X5; - case 54: - return Containers.GENERIC_9X6; - } + return getContainers(inventory.getBukkitInventory().getSize()); } }; - container.setTitle(new ChatComponentText(title)); + container.setTitle(new ChatComponentText(view.getTitle())); container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); if (container == null) { @@ -272,6 +219,63 @@ public class PlayerDataManager implements IPlayerDataManager { } + private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) { + if (inventory instanceof SpecialEnderChest) { + return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest"); + } else if (inventory instanceof SpecialPlayerInventory) { + return new OpenInventoryView(player, inventory, "container.player", "'s Inventory"); + } else { + return null; + } + } + + private @NotNull Containers getContainers(int inventorySize) { + switch (inventorySize) { + case 9: + return Containers.GENERIC_9X1; + case 18: + return Containers.GENERIC_9X2; + case 36: + return Containers.GENERIC_9X4; + case 41: // PLAYER + case 45: + return Containers.GENERIC_9X5; + case 54: + return Containers.GENERIC_9X6; + case 27: + default: + return Containers.GENERIC_9X3; + } + } + + @Override + public int convertToPlayerSlot(InventoryView view, int rawSlot) { + int topSize = view.getTopInventory().getSize(); + if (topSize <= rawSlot) { + // Slot is not inside special inventory, use Bukkit logic. + return view.convertSlot(rawSlot); + } + + // Main inventory, slots 0-26 -> 9-35 + if (rawSlot < 27) { + return rawSlot + 9; + } + // Hotbar, slots 27-35 -> 0-8 + if (rawSlot < 36) { + return rawSlot - 27; + } + // Armor, slots 36-39 -> 39-36 + if (rawSlot < 40) { + return 36 + (39 - rawSlot); + } + // Off hand + if (rawSlot == 40) { + return 40; + } + // Drop slots, "out of inventory" + return -1; + } + @Override public void sendSystemMessage(@NotNull Player player, @NotNull String message) { int newline = message.indexOf('\n'); diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java index ba33e94..24cd9b0 100644 --- a/plugin/src/main/java/com/lishid/openinv/OpenInv.java +++ b/plugin/src/main/java/com/lishid/openinv/OpenInv.java @@ -150,6 +150,20 @@ public class OpenInv extends JavaPlugin implements IOpenInv { } } + /** + * Convert a raw slot number into a player inventory slot number. + * + *

Note that this method is specifically for converting an ISpecialPlayerInventory slot number into a regular + * player inventory slot number. + * + * @param view the open inventory view + * @param rawSlot the raw slot in the view + * @return the converted slot number + */ + public int convertToPlayerSlot(InventoryView view, int rawSlot) { + return this.accessor.getPlayerDataManager().convertToPlayerSlot(view, rawSlot); + } + @Override public boolean disableSaving() { return this.getConfig().getBoolean("settings.disable-saving", false); diff --git a/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java b/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java index 92c86af..b217479 100644 --- a/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java +++ b/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java @@ -54,6 +54,18 @@ public interface IPlayerDataManager { @Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory); + /** + * Convert a raw slot number into a player inventory slot number. + * + *

Note that this method is specifically for converting an ISpecialPlayerInventory slot number into a regular + * player inventory slot number. + * + * @param view the open inventory view + * @param rawSlot the raw slot in the view + * @return the converted slot number + */ + int convertToPlayerSlot(InventoryView view, int rawSlot); + void sendSystemMessage(@NotNull Player player, @NotNull String message); @NotNull diff --git a/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java b/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java new file mode 100644 index 0000000..8fc6f09 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011-2021 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; + +import com.lishid.openinv.OpenInv; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.jetbrains.annotations.NotNull; + +public class OpenInventoryView extends InventoryView { + + private final Player player; + private final ISpecialInventory inventory; + private final String titleKey; + private final String titleDefaultSuffix; + private String title; + + public OpenInventoryView(Player player, ISpecialInventory inventory, String titleKey, String titleDefaultSuffix) { + this.player = player; + this.inventory = inventory; + this.titleKey = titleKey; + this.titleDefaultSuffix = titleDefaultSuffix; + } + + @Override + public @NotNull Inventory getTopInventory() { + return inventory.getBukkitInventory(); + } + + @Override + public @NotNull Inventory getBottomInventory() { + return getPlayer().getInventory(); + } + + @Override + public @NotNull HumanEntity getPlayer() { + return player; + } + + @Override + public @NotNull InventoryType getType() { + return inventory.getBukkitInventory().getType(); + } + + @Override + public @NotNull String getTitle() { + if (title == null) { + HumanEntity owner = getPlayer(); + + String localTitle = OpenInv.getPlugin(OpenInv.class) + .getLocalizedMessage( + owner, + titleKey, + "%player%", + owner.getName()); + if (localTitle != null) { + title = localTitle; + } else { + title = owner.getName() + titleDefaultSuffix; + } + } + + return title; + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java b/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java index 676635a..eee6686 100644 --- a/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java +++ b/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java @@ -20,6 +20,9 @@ import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.util.InventoryAccess; import com.lishid.openinv.util.Permissions; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.bukkit.GameMode; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; @@ -32,8 +35,10 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryInteractEvent; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Listener for inventory-related events to prevent modification of inventories where not allowed. @@ -67,11 +72,6 @@ public class InventoryListener implements Listener { return; } - // Only specially handle actions in the player's own inventory. - if (!event.getWhoClicked().equals(event.getView().getTopInventory().getHolder())) { - return; - } - // Safe cast - has to be a player to be the holder of a special player inventory. Player player = (Player) event.getWhoClicked(); @@ -102,14 +102,65 @@ public class InventoryListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onInventoryDrag(@NotNull final InventoryDragEvent event) { - handleInventoryInteract(event); + if (handleInventoryInteract(event)) { + return; + } + + InventoryView view = event.getView(); + int topSize = view.getTopInventory().getSize(); + + // Get bottom inventory active slots as player inventory slots. + Set slots = event.getRawSlots().stream() + .filter(slot -> slot >= topSize) + .map(slot -> plugin.convertToPlayerSlot(view, slot)).collect(Collectors.toSet()); + + int overlapLosses = 0; + + // Count overlapping slots. + for (Map.Entry newItem : event.getNewItems().entrySet()) { + int rawSlot = newItem.getKey(); + + // Skip bottom inventory slots. + if (rawSlot >= topSize) { + continue; + } + + int convertedSlot = plugin.convertToPlayerSlot(view, rawSlot); + + if (slots.contains(convertedSlot)) { + overlapLosses += getCountDiff(view.getItem(rawSlot), newItem.getValue()); + } + } + + // Allow no overlap to proceed as usual. + if (overlapLosses < 1) { + return; + } + + ItemStack cursor = event.getCursor(); + if (cursor != null) { + cursor.setAmount(cursor.getAmount() + overlapLosses); + } else { + cursor = event.getOldCursor().clone(); + cursor.setAmount(overlapLosses); + } + + event.setCursor(cursor); + } + + private int getCountDiff(@Nullable ItemStack original, @NotNull ItemStack result) { + if (original == null || original.getType() != result.getType()) { + return result.getAmount(); + } + + return result.getAmount() - original.getAmount(); } /** * Handle common InventoryInteractEvent functions. * * @param event the InventoryInteractEvent - * @return true unless the top inventory is an opened player inventory + * @return true unless the top inventory is the holder's own inventory */ private boolean handleInventoryInteract(@NotNull final InventoryInteractEvent event) { HumanEntity entity = event.getWhoClicked(); @@ -147,7 +198,8 @@ public class InventoryListener implements Listener { return true; } - return false; + // Only specially handle actions in the player's own inventory. + return !event.getWhoClicked().equals(event.getView().getTopInventory().getHolder()); } } From 6e5c332272d053aaac96616b9d951ece34e1a02e Mon Sep 17 00:00:00 2001 From: Jikoo Date: Tue, 16 Mar 2021 23:42:30 -0400 Subject: [PATCH 5/8] Extract player implementation --- .../openinv/internal/v1_16_R3/OpenPlayer.java | 69 +++++++++++++++++++ .../internal/v1_16_R3/PlayerDataManager.java | 41 +---------- 2 files changed, 70 insertions(+), 40 deletions(-) create mode 100644 internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/OpenPlayer.java diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/OpenPlayer.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/OpenPlayer.java new file mode 100644 index 0000000..def3f96 --- /dev/null +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/OpenPlayer.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2021 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_16_R3; + +import java.io.File; +import java.io.FileOutputStream; +import net.minecraft.server.v1_16_R3.EntityPlayer; +import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools; +import net.minecraft.server.v1_16_R3.NBTTagCompound; +import net.minecraft.server.v1_16_R3.WorldNBTStorage; +import org.apache.logging.log4j.LogManager; +import org.bukkit.craftbukkit.v1_16_R3.CraftServer; +import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; + +public class OpenPlayer extends CraftPlayer { + + public OpenPlayer(CraftServer server, EntityPlayer entity) { + super(server, entity); + } + + @Override + public void saveData() { + super.saveData(); + EntityPlayer player = this.getHandle(); + // See net.minecraft.server.WorldNBTStorage#save(EntityPlayer) + try { + WorldNBTStorage worldNBTStorage = player.server.getPlayerList().playerFileData; + + NBTTagCompound playerData = player.save(new NBTTagCompound()); + + if (!isOnline()) { + // Special case: save old vehicle data + NBTTagCompound oldData = worldNBTStorage.load(player); + + if (oldData != null && oldData.hasKeyOfType("RootVehicle", 10)) { + // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) + playerData.set("RootVehicle", oldData.getCompound("RootVehicle")); + } + } + + File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat.tmp"); + File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat"); + + NBTCompressedStreamTools.a(playerData, new FileOutputStream(file)); + + if (file1.exists() && !file1.delete() || !file.renameTo(file1)) { + LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); + } + + } catch (Exception e) { + LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); + } + } + +} diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java index 4c029db..3871520 100644 --- a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java @@ -20,8 +20,6 @@ import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; -import java.io.File; -import java.io.FileOutputStream; import java.lang.reflect.Field; import net.minecraft.server.v1_16_R3.ChatComponentText; import net.minecraft.server.v1_16_R3.ChatMessageType; @@ -30,16 +28,12 @@ import net.minecraft.server.v1_16_R3.Containers; import net.minecraft.server.v1_16_R3.Entity; import net.minecraft.server.v1_16_R3.EntityPlayer; import net.minecraft.server.v1_16_R3.MinecraftServer; -import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools; -import net.minecraft.server.v1_16_R3.NBTTagCompound; import net.minecraft.server.v1_16_R3.PacketPlayOutChat; import net.minecraft.server.v1_16_R3.PacketPlayOutOpenWindow; import net.minecraft.server.v1_16_R3.PlayerInteractManager; import net.minecraft.server.v1_16_R3.SystemUtils; import net.minecraft.server.v1_16_R3.World; -import net.minecraft.server.v1_16_R3.WorldNBTStorage; import net.minecraft.server.v1_16_R3.WorldServer; -import org.apache.logging.log4j.LogManager; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; @@ -131,40 +125,7 @@ public class PlayerDataManager implements IPlayerDataManager { bukkitEntity.setAccessible(true); - bukkitEntity.set(player, new CraftPlayer(player.server.server, player) { - @Override - public void saveData() { - super.saveData(); - // See net.minecraft.server.WorldNBTStorage#save(EntityPlayer) - try { - WorldNBTStorage worldNBTStorage = player.server.getPlayerList().playerFileData; - - NBTTagCompound playerData = player.save(new NBTTagCompound()); - - if (!isOnline()) { - // Special case: save old vehicle data - NBTTagCompound oldData = worldNBTStorage.load(player); - - if (oldData != null && oldData.hasKeyOfType("RootVehicle", 10)) { - // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) - playerData.set("RootVehicle", oldData.getCompound("RootVehicle")); - } - } - - File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat.tmp"); - File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat"); - - NBTCompressedStreamTools.a(playerData, new FileOutputStream(file)); - - if (file1.exists() && !file1.delete() || !file.renameTo(file1)) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); - } - - } catch (Exception e) { - LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString()); - } - } - }); + bukkitEntity.set(player, new OpenPlayer(player.server.server, player)); } @NotNull From 3ba82683ecb839cdae92cc0c203c043486492555 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Wed, 17 Mar 2021 00:09:10 -0400 Subject: [PATCH 6/8] Fix double chest custom names not displaying Closes #175 --- .../internal/v1_16_R3/AnySilentContainer.java | 29 +++++-------------- .../internal/v1_16_R3/PlayerDataManager.java | 2 +- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/AnySilentContainer.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/AnySilentContainer.java index e6a2083..5d78617 100644 --- a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/AnySilentContainer.java +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/AnySilentContainer.java @@ -190,29 +190,8 @@ public class AnySilentContainer implements IAnySilentContainer { InventoryEnderChest enderChest = player.getEnderChest(); enderChest.a((TileEntityEnderChest) tile); player.openContainer(new TileInventory((containerCounter, playerInventory, ignored) -> { - Containers containers; + Containers containers = PlayerDataManager.getContainers(enderChest.getSize()); int rows = enderChest.getSize() / 9; - switch (rows) { - case 1: - containers = Containers.GENERIC_9X1; - break; - case 2: - containers = Containers.GENERIC_9X2; - break; - case 3: - default: - containers = Containers.GENERIC_9X3; - break; - case 4: - containers = Containers.GENERIC_9X4; - break; - case 5: - containers = Containers.GENERIC_9X5; - break; - case 6: - containers = Containers.GENERIC_9X6; - break; - } return new ContainerChest(containers, containerCounter, playerInventory, enderChest, rows); }, new ChatMessage("container.enderchest"))); bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED); @@ -262,6 +241,12 @@ public class AnySilentContainer implements IAnySilentContainer { } public IChatBaseComponent getScoreboardDisplayName() { + if (leftChest.hasCustomName()) { + return leftChest.getScoreboardDisplayName(); + } + if (rightChest.hasCustomName()) { + return rightChest.getScoreboardDisplayName(); + } return new ChatMessage("container.chestDouble"); } }; diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java index 3871520..701fdba 100644 --- a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java @@ -190,7 +190,7 @@ public class PlayerDataManager implements IPlayerDataManager { } } - private @NotNull Containers getContainers(int inventorySize) { + static @NotNull Containers getContainers(int inventorySize) { switch (inventorySize) { case 9: return Containers.GENERIC_9X1; From 1d5a836fd0b558c02b3f0fc44907e2ce3417f0c7 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Thu, 18 Mar 2021 16:38:41 -0400 Subject: [PATCH 7/8] Partially automate release changelog --- .github/workflows/ci.yml | 4 +++ scripts/generate_changelog.sh | 67 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 scripts/generate_changelog.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e65f0f6..a73e107 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,9 @@ jobs: - name: Download Artifacts uses: actions/download-artifact@v2 + - name: Generate changelog + run: . scripts/generate_changelog.sh + - name: Create Release id: create-release uses: actions/create-release@v1 @@ -68,6 +71,7 @@ jobs: with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} + body: ${{ env.GENERATED_CHANGELOG }} draft: true prerelease: false diff --git a/scripts/generate_changelog.sh b/scripts/generate_changelog.sh new file mode 100644 index 0000000..72c823d --- /dev/null +++ b/scripts/generate_changelog.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# +# Copyright (C) 2011-2021 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 . +# + +# A script for generating a changelog from Git. +# +# Note that this script is designed for use in GitHub Actions, and is not +# particularly robust nor configurable. Run from project parent directory. + +# Query GitHub for the username of the given email address. +# Falls through to the given author name. +lookup_email_username() { + lookup=$(curl -G --data-urlencode "q=$1 in:email" https://api.github.com/search/users -H 'Accept: application/vnd.github.v3+json' | grep '"login":' | sed -e 's/^.*": "//g' -e 's/",.*$//g') + + if [[ $lookup ]]; then + echo -n "@$lookup" + else + echo "$2" + fi +} + +# Use formatted log to pull authors list +authors_raw=$(git log --pretty=format:"%ae|%an" "$(git describe --tags --abbrev=0 @^)"..@) +readarray -t authors <<<"$authors_raw" + +declare -A author_data + +for author in "${authors[@]}"; do + # Match author email + author_email=${author%|*} + # Convert to lower case + author_email=${author_email,,} + # Match author name + author_name=${author##*|} + if [[ -n ${author_data[$author_email]} ]]; then + # Skip emails we already have data for + continue + fi + + # Fetch and store author GitHub username by email + author_data[$author_email]=$(lookup_email_username "$author_email" "$author_name") +done + +# Fetch actual formatted changelog +changelog=$(git log --pretty=format:"%s (%h) - %ae" "$(git describe --tags --abbrev=0 @^)"..@) + +for author_email in "${!author_data[@]}"; do + # Ignore case when matching + shopt -s nocasematch + # Match and replace email + changelog=${changelog//$author_email/${author_data[$author_email]}} +done + +echo "GENERATED_CHANGELOG<> "$GITHUB_ENV" From 6563b4f6cef3741f67b7df7156cca47241ebc8e8 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Thu, 18 Mar 2021 20:31:45 -0400 Subject: [PATCH 8/8] Migrate API-only functions out of PlayerDataManager With the update to 1.16 there's no need to maintain multiple copies of the same code. Additionally, in 1.16 the action bar now supports JSON text. --- .../internal/v1_16_R3/PlayerDataManager.java | 23 ------------------- .../main/java/com/lishid/openinv/OpenInv.java | 20 +++++++++++++--- .../openinv/internal/IPlayerDataManager.java | 16 +++---------- 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java index 701fdba..5a29ceb 100644 --- a/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java +++ b/internal/v1_16_R3/src/main/java/com/lishid/openinv/internal/v1_16_R3/PlayerDataManager.java @@ -22,16 +22,13 @@ import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; import java.lang.reflect.Field; import net.minecraft.server.v1_16_R3.ChatComponentText; -import net.minecraft.server.v1_16_R3.ChatMessageType; import net.minecraft.server.v1_16_R3.Container; import net.minecraft.server.v1_16_R3.Containers; import net.minecraft.server.v1_16_R3.Entity; import net.minecraft.server.v1_16_R3.EntityPlayer; import net.minecraft.server.v1_16_R3.MinecraftServer; -import net.minecraft.server.v1_16_R3.PacketPlayOutChat; import net.minecraft.server.v1_16_R3.PacketPlayOutOpenWindow; import net.minecraft.server.v1_16_R3.PlayerInteractManager; -import net.minecraft.server.v1_16_R3.SystemUtils; import net.minecraft.server.v1_16_R3.World; import net.minecraft.server.v1_16_R3.WorldServer; import org.bukkit.Bukkit; @@ -237,24 +234,4 @@ public class PlayerDataManager implements IPlayerDataManager { return -1; } - @Override - public void sendSystemMessage(@NotNull Player player, @NotNull String message) { - int newline = message.indexOf('\n'); - if (newline != -1) { - // No newlines in action bar chat. - message = message.substring(0, newline); - } - - if (message.isEmpty()) { - return; - } - - EntityPlayer nmsPlayer = getHandle(player); - - // For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text. - if (nmsPlayer.playerConnection != null) { - nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO, SystemUtils.b)); - } - } - } diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java index 24cd9b0..8137584 100644 --- a/plugin/src/main/java/com/lishid/openinv/OpenInv.java +++ b/plugin/src/main/java/com/lishid/openinv/OpenInv.java @@ -42,6 +42,8 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Consumer; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; @@ -299,9 +301,21 @@ public class OpenInv extends JavaPlugin implements IOpenInv { public void sendSystemMessage(@NotNull Player player, @NotNull String key) { String message = this.languageManager.getValue(key, getLocale(player)); - if (message != null) { - this.accessor.getPlayerDataManager().sendSystemMessage(player, message); + if (message == null) { + return; } + + int newline = message.indexOf('\n'); + if (newline != -1) { + // No newlines in action bar chat. + message = message.substring(0, newline); + } + + if (message.isEmpty()) { + return; + } + + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); } public @Nullable String getLocalizedMessage(@NotNull CommandSender sender, @NotNull String key) { @@ -314,7 +328,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv { private @Nullable String getLocale(@NotNull CommandSender sender) { if (sender instanceof Player) { - return this.accessor.getPlayerDataManager().getLocale((Player) sender); + return ((Player) sender).getLocale(); } else { return this.getConfig().getString("settings.locale", "en_us"); } diff --git a/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java b/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java index b217479..1a81491 100644 --- a/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java +++ b/plugin/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java @@ -32,16 +32,14 @@ public interface IPlayerDataManager { * @param offline the OfflinePlayer * @return the Player loaded */ - @Nullable - Player loadPlayer(@NotNull OfflinePlayer offline); + @Nullable Player loadPlayer(@NotNull OfflinePlayer offline); /** * Creates a new Player from an existing one that will function slightly better offline. * * @return the Player */ - @NotNull - Player inject(@NotNull Player player); + @NotNull Player inject(@NotNull Player player); /** * Opens an ISpecialInventory for a Player. @@ -51,8 +49,7 @@ public interface IPlayerDataManager { *` * @return the InventoryView opened */ - @Nullable - InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory); + @Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory); /** * Convert a raw slot number into a player inventory slot number. @@ -66,11 +63,4 @@ public interface IPlayerDataManager { */ int convertToPlayerSlot(InventoryView view, int rawSlot); - void sendSystemMessage(@NotNull Player player, @NotNull String message); - - @NotNull - default String getLocale(Player player) { - return player.getLocale(); - } - }