diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6489274..a73e107 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,18 +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.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 + run: . scripts/install_spigot_dependencies.sh - name: Build With Maven run: mvn -e clean package -am -P all @@ -70,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 @@ -78,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/api/pom.xml b/api/pom.xml index d42d670..914071c 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 770345b..2bbd718 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 021a5ce..0000000 --- a/internal/v1_15_R1/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.5-TF - - - openinvadapter1_15_R1 - OpenInvAdapter1_15_R1 - - - - org.spigotmc - spigot - 1.15.2-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.5-TF - - - - - - - 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 ef365b0..0000000 --- a/internal/v1_16_R2/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.5-TF - - - openinvadapter1_16_R2 - OpenInvAdapter1_16_R2 - - - - org.spigotmc - spigot - 1.16.3-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.5-TF - - - - - - - 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_16_R3/pom.xml b/internal/v1_16_R3/pom.xml index 7ead3e9..4b9fa78 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/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/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 e0737c5..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 @@ -16,32 +16,21 @@ 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; 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.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; -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; 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; @@ -49,10 +38,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; @@ -136,40 +122,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 @@ -195,68 +148,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,24 +177,61 @@ public class PlayerDataManager implements IPlayerDataManager { } - @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)); + 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; } } + static @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; + } + } diff --git a/internal/v1_8_R3/pom.xml b/internal/v1_8_R3/pom.xml deleted file mode 100644 index b5951a8..0000000 --- a/internal/v1_8_R3/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - 4.0.0 - - - com.lishid - openinvinternal - 4.1.5-TF - - - openinvadapter1_8_R3 - OpenInvAdapter1_8_R3 - - - - org.spigotmc - spigot - 1.8.8-R0.1-SNAPSHOT - provided - - - com.lishid - openinvplugincore - 4.1.5-TF - - - - - - - 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/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java index ba33e94..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; @@ -150,6 +152,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); @@ -285,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) { @@ -300,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 92c86af..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,14 +49,18 @@ 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); - void sendSystemMessage(@NotNull Player player, @NotNull String message); - - @NotNull - default String getLocale(Player player) { - return player.getLocale(); - } + /** + * 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); } 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 33221f2..eee6686 100644 --- a/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java +++ b/plugin/src/main/java/com/lishid/openinv/listeners/InventoryListener.java @@ -16,20 +16,29 @@ 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 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; 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.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. @@ -38,14 +47,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 +67,139 @@ 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; + } + + // 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) { + 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 void onInventoryInteract(InventoryInteractEvent event) { + 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 the holder's own 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; + } + + // Only specially handle actions in the player's own inventory. + return !event.getWhoClicked().equals(event.getView().getTopInventory().getHolder()); } } 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: 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" 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