mirror of
https://github.com/TotalFreedomMC/OpenInv.git
synced 2024-12-22 16:05:03 +00:00
Drop 1.8/1.15/1.16.3 support (#185)
With the recent uptick in requests for support by people running 1.12 who have recently updated past Java 9, I revisited the supported versions. First, the "modern" versions: 1.15 is run by 2.9% of servers, 1.16.3 by 5%. Since all of these versions are supported to ease the transition of updating servers and servers have updated, there's no real reason to keep them around. It's a lot easier if you can update a plugin and just have it work on both versions rather than push all the plugin updates to master with the server update, but none of these versions have any reason for long-term support. Regarding heavily outdated server software: As of the time of writing, 1.8 and 1.12 have market shares of 8.6% and 8.5% of servers respectively. Regarding 1.8: 1.8 support is already a bit wonky - with the changes made to inventory names, it's not (easily) possible to bridge the gap, and future changes will make that more and more difficult. People use 1.8 because they disliked the 1.9 combat changes, but there are plugins that fully rework combat to how it used to be. I have yet to hear a compelling argument that cannot be resolved with plugins. In the interest of my own sanity (handling and backporting the inventory name change in particular was a real humdinger) I will no longer be backporting changes to 1.8. Regarding 1.12: I am honestly not sure why people are not updating. I get it, 1.13 and the flattening was a rough transition, but pretty much every developer active at the time bridged the gap. If your server is heavily dependent on some software only available at that time, you can live with other software available at that time. At the time of 1.12's release, Java 9 was not released. Either update your server, downgrade Java, or fork OpenInv and backport Java 9 support yourself.
This commit is contained in:
parent
dad00d2d9c
commit
1bd7932cc5
20 changed files with 3 additions and 4299 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -36,9 +36,6 @@ jobs:
|
|||
mkdir ~/buildtools
|
||||
cd ~/buildtools
|
||||
wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
|
||||
java -jar BuildTools.jar --rev 1.8.8
|
||||
java -jar BuildTools.jar --rev 1.15.2
|
||||
java -jar BuildTools.jar --rev 1.16.3
|
||||
java -jar BuildTools.jar --rev 1.16.4
|
||||
|
||||
- name: Build With Maven
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
<profile>
|
||||
<id>all</id>
|
||||
<modules>
|
||||
<module>v1_8_R3</module>
|
||||
<module>v1_15_R1</module>
|
||||
<module>v1_16_R2</module>
|
||||
<module>v1_16_R3</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_15_R1</artifactId>
|
||||
<name>OpenInvAdapter1_15_R1</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ItemStack> 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<ItemStack> 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<HumanEntity> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ItemStack> items, armor, extraSlots;
|
||||
private List<NonNullList<ItemStack>> 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<ItemStack> 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<ItemStack> list = null;
|
||||
for (NonNullList<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> getContents() {
|
||||
return this.f.stream().flatMap(List::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> 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<HumanEntity> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_16_R2</artifactId>
|
||||
<name>OpenInvAdapter1_16_R2</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.16.3-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ItemStack> 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<ItemStack> 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<HumanEntity> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ItemStack> items, armor, extraSlots;
|
||||
private List<NonNullList<ItemStack>> 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<ItemStack> 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<ItemStack> list = null;
|
||||
for (NonNullList<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> getContents() {
|
||||
return this.f.stream().flatMap(List::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> 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<HumanEntity> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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<ItemStack> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,74 +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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_8_R3</artifactId>
|
||||
<name>OpenInvAdapter1_8_R3</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
<version>4.1.6-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue