Compare commits

...
6 Commits
13 changed files with 217 additions and 247 deletions

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>openinvparent</artifactId>
<groupId>com.lishid</groupId>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</parent>
<artifactId>openinvapi</artifactId>
@@ -16,8 +16,19 @@
package com.lishid.openinv.internal;
import org.bukkit.Material;
import org.bukkit.block.Barrel;
import org.bukkit.block.Block;
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.util.BoundingBox;
import org.jetbrains.annotations.NotNull;
public interface IAnySilentContainer {
@@ -41,14 +52,99 @@ public interface IAnySilentContainer {
*/
void deactivateContainer(@NotNull Player player);
/**
* @deprecated use {@link #isAnyContainerNeeded(Block)}
* @param player the player opening the container
* @param block the block
* @return true if the container is blocked
*/
@Deprecated
default boolean isAnyContainerNeeded(@NotNull Player player, @NotNull Block block) {
return isAnyContainerNeeded(block);
}
/**
* Checks if the container at the given coordinates is blocked.
*
* @param player the Player opening the container
* @param block the Block
* @return true if the container is blocked
*/
boolean isAnyContainerNeeded(@NotNull Player player, @NotNull Block block);
default boolean isAnyContainerNeeded(@NotNull 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 (isChestBlocked(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 isChestBlocked(relative);
}
default boolean isChestBlocked(Block chest) {
org.bukkit.block.Block relative = chest.getRelative(0, 1, 0);
return relative.getType().isOccluding()
|| chest.getWorld().getNearbyEntities(BoundingBox.of(relative), entity -> entity instanceof Cat).size() > 0;
}
/**
* Checks if the given block is a container which can be unblocked or silenced.
@@ -56,6 +152,14 @@ public interface IAnySilentContainer {
* @param block the BlockState
* @return true if the Block is a supported container
*/
boolean isAnySilentContainer(@NotNull Block block);
default boolean isAnySilentContainer(@NotNull Block block) {
if (block.getType() == Material.ENDER_CHEST) {
return true;
}
BlockState state = block.getState();
return state instanceof org.bukkit.block.Chest
|| state instanceof org.bukkit.block.ShulkerBox
|| state instanceof org.bukkit.block.Barrel;
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>com.lishid</groupId>
<artifactId>openinvparent</artifactId>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</parent>
<artifactId>openinvassembly</artifactId>
+1 -1
View File
@@ -23,7 +23,7 @@
<artifactId>openinvparent</artifactId>
<groupId>com.lishid</groupId>
<relativePath>../../pom.xml</relativePath>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</parent>
<artifactId>openinvadapter1_16_R3</artifactId>
@@ -48,18 +48,8 @@ import net.minecraft.server.v1_16_R3.TileInventory;
import net.minecraft.server.v1_16_R3.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 {
@@ -76,94 +66,6 @@ public class AnySilentContainer implements IAnySilentContainer {
}
}
@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) {
+1 -1
View File
@@ -23,7 +23,7 @@
<artifactId>openinvparent</artifactId>
<groupId>com.lishid</groupId>
<relativePath>../../pom.xml</relativePath>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</parent>
<artifactId>openinvadapter1_17_R1</artifactId>
@@ -50,18 +50,8 @@ import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.block.state.properties.BlockPropertyChestType;
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 {
@@ -79,91 +69,6 @@ public class AnySilentContainer implements IAnySilentContainer {
}
}
@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 directional)) {
// Shouldn't be possible. Just in case, demand AnyChest.
return true;
}
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) || ((Chest) blockData).getType() == Chest.Type.SINGLE) {
return false;
}
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 relativeChest)) {
return false;
}
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,
@@ -336,10 +241,6 @@ public class AnySilentContainer implements IAnySilentContainer {
try {
this.playerInteractManagerGamemode.setAccessible(true);
this.playerInteractManagerGamemode.set(player.d, gameMode);
// TODO: may need additional calls to update abilities to prevent container sound + animation
// gameMode.a(player.getAbilities());
// player.updateAbilities();
// should be the fix if it doesn't work as-is
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>openinvparent</artifactId>
<groupId>com.lishid</groupId>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</parent>
<artifactId>openinvplugincore</artifactId>
@@ -35,10 +35,12 @@ import com.lishid.openinv.util.ConfigUpdater;
import com.lishid.openinv.util.InternalAccessor;
import com.lishid.openinv.util.LanguageManager;
import com.lishid.openinv.util.Permissions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Consumer;
@@ -88,7 +90,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
// Check if inventory is stored, and if it is, remove it and eject all viewers
if (OpenInv.this.inventories.containsKey(key)) {
Inventory inv = OpenInv.this.inventories.remove(key).getBukkitInventory();
List<HumanEntity> viewers = inv.getViewers();
List<HumanEntity> viewers = new ArrayList<>(inv.getViewers());
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
entity.closeInventory();
}
@@ -97,7 +99,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
// Check if ender chest is stored, and if it is, remove it and eject all viewers
if (OpenInv.this.enderChests.containsKey(key)) {
Inventory inv = OpenInv.this.enderChests.remove(key).getBukkitInventory();
List<HumanEntity> viewers = inv.getViewers();
List<HumanEntity> viewers = new ArrayList<>(inv.getViewers());
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
entity.closeInventory();
}
@@ -126,29 +128,23 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
}
if (this.inventories.containsKey(key)) {
Iterator<HumanEntity> iterator = this.inventories.get(key).getBukkitInventory().getViewers().iterator();
//noinspection WhileLoopReplaceableByForEach
while (iterator.hasNext()) {
HumanEntity human = iterator.next();
// If player has permission or is in the same world, allow continued access
// Just in case, also allow null worlds.
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
continue;
}
human.closeInventory();
}
kickCrossWorldViewers(player, this.inventories.get(key));
}
if (this.enderChests.containsKey(key)) {
Iterator<HumanEntity> iterator = this.enderChests.get(key).getBukkitInventory().getViewers().iterator();
//noinspection WhileLoopReplaceableByForEach
while (iterator.hasNext()) {
HumanEntity human = iterator.next();
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
continue;
}
human.closeInventory();
kickCrossWorldViewers(player, this.enderChests.get(key));
}
}
private void kickCrossWorldViewers(Player player, ISpecialInventory inventory) {
List<HumanEntity> viewers = new ArrayList<>(inventory.getBukkitInventory().getViewers());
for (HumanEntity human : viewers) {
// If player has permission or is in the same world, allow continued access
// Just in case, also allow null worlds.
if (Permissions.CROSSWORLD.hasPermission(human) || Objects.equals(human.getWorld(), player.getWorld())) {
continue;
}
human.closeInventory();
}
}
@@ -326,7 +322,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
return this.languageManager.getValue(key, getLocale(sender), replacements);
}
private @Nullable String getLocale(@NotNull CommandSender sender) {
private @NotNull String getLocale(@NotNull CommandSender sender) {
if (sender instanceof Player) {
return ((Player) sender).getLocale();
} else {
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2021 lishid. All rights reserved.
* Copyright (C) 2011-2022 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
@@ -19,11 +19,13 @@ package com.lishid.openinv.util;
import com.lishid.openinv.internal.IAnySilentContainer;
import com.lishid.openinv.internal.IPlayerDataManager;
import com.lishid.openinv.internal.ISpecialEnderChest;
import com.lishid.openinv.internal.ISpecialInventory;
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
public class InternalAccessor {
@@ -132,6 +134,23 @@ public class InternalAccessor {
throw new IllegalArgumentException(message);
}
private <T extends ISpecialInventory> T createSpecialInventory(
@NotNull Class<? extends T> assignableClass,
@NotNull String className,
@NotNull Player player,
boolean online) throws InstantiationException {
if (!this.supported) {
throw new IllegalStateException(String.format("Unsupported server version %s!", this.version));
}
try {
return this.createObject(assignableClass, className, player, online);
} catch (Exception original) {
InstantiationException exception = new InstantiationException(String.format("Unable to create a new %s", className));
exception.initCause(original.fillInStackTrace());
throw exception;
}
}
/**
* Creates an instance of the IAnySilentContainer implementation for the current server version.
*
@@ -187,14 +206,7 @@ public class InternalAccessor {
* @throws InstantiationException if the ISpecialEnderChest could not be instantiated
*/
public ISpecialEnderChest newSpecialEnderChest(final Player player, final boolean online) throws InstantiationException {
if (!this.supported) {
throw new IllegalStateException(String.format("Unsupported server version %s!", this.version));
}
try {
return this.createObject(ISpecialEnderChest.class, "SpecialEnderChest", player, online);
} catch (Exception e) {
throw new InstantiationException(String.format("Unable to create a new ISpecialEnderChest: %s", e.getMessage()));
}
return this.createSpecialInventory(ISpecialEnderChest.class, "SpecialEnderChest", player, online);
}
/**
@@ -206,14 +218,7 @@ public class InternalAccessor {
* @throws InstantiationException if the ISpecialPlayerInventory could not be instantiated
*/
public ISpecialPlayerInventory newSpecialPlayerInventory(final Player player, final boolean online) throws InstantiationException {
if (!this.supported) {
throw new IllegalStateException(String.format("Unsupported server version %s!", this.version));
}
try {
return this.createObject(ISpecialPlayerInventory.class, "SpecialPlayerInventory", player, online);
} catch (Exception e) {
throw new InstantiationException(String.format("Unable to create a new ISpecialPlayerInventory: %s", e.getMessage()));
}
return this.createSpecialInventory(ISpecialPlayerInventory.class, "SpecialPlayerInventory", player, online);
}
}
+31
View File
@@ -0,0 +1,31 @@
# Translated into Chinese Simplified by Flandre_tw
messages:
error:
consoleUnsupported: 该命令无法在后台执行。
lootNotGenerated: '&c奖励箱尚未生成 ! 请关闭 &b/silentcontainer&c。'
invalidMaterial: '&c无效的物品 : "%target%"'
invalidNumber: '&c无效的数字 : "%target%"'
invalidPlayer: '&c玩家不存在 !'
permissionOpenSelf: '&c你无法开启自己的物品栏。'
permissionEnderAll: '&c你无法开启其他玩家的末影箱。'
permissionExempt: '&c%target% 的物品栏受到保护。'
permissionCrossWorld: '&c%target% 不在你所在的世界。'
permissionPlayerOnline: '&c你无法开启线上玩家的物品栏。'
permissionPlayerOffline: '&c你无法开启离线玩家的物品栏。'
commandException: '&c发生错误,请查看后台。'
info:
containerBlocked: 你正在开启受阻挡的储物箱。
containerBlockedSilent: 你正在悄悄开启受阻挡的储物箱。
containerSilent: 你正在悄悄开启储物箱。
settingState: '%setting% : %state%'
player:
noMatches: 找不到持有 %target% 的玩家。
matches: '找到持有 %target% 的玩家 : %detail%'
container:
noMatches: 找不到放有 %target% 的储物箱。
matches: '找到放有 %target% 的储物箱 : %detail%'
'true': '开启'
'false': '关闭'
container:
player: '%player% 的物品栏'
enderchest: '%player% 的末影箱'
+31
View File
@@ -0,0 +1,31 @@
# Translated into Chinese Traditional by Flandre_tw
messages:
error:
consoleUnsupported: 該指令無法在控制台執行。
lootNotGenerated: '&c獎勵箱尚未生成 ! 請關閉 &b/silentcontainer&c。'
invalidMaterial: '&c無效的物品 : "%target%"'
invalidNumber: '&c無效的數字 : "%target%"'
invalidPlayer: '&c玩家不存在 !'
permissionOpenSelf: '&c你無法開啟自己的物品欄。'
permissionEnderAll: '&c你無法開啟其他玩家的終界箱。'
permissionExempt: '&c%target% 的物品欄受到保護。'
permissionCrossWorld: '&c%target% 不在你所在的世界。'
permissionPlayerOnline: '&c你無法開啟線上玩家的物品欄。'
permissionPlayerOffline: '&c你無法開啟離線玩家的物品欄。'
commandException: '&c發生錯誤,請查看控制台。'
info:
containerBlocked: 你正在開啟受阻擋的儲物箱。
containerBlockedSilent: 你正在悄悄開啟受阻擋的儲物箱。
containerSilent: 你正在悄悄開啟儲物箱。
settingState: '%setting% : %state%'
player:
noMatches: 找不到持有 %target% 的玩家。
matches: '找到持有 %target% 的玩家 : %detail%'
container:
noMatches: 找不到放有 %target% 的儲物箱。
matches: '找到放有 %target% 的儲物箱 : %detail%'
'true': '開啟'
'false': '關閉'
container:
player: '%player% 的物品欄'
enderchest: '%player% 的終界箱'
+3 -3
View File
@@ -21,7 +21,7 @@
<artifactId>openinvparent</artifactId>
<name>OpenInv</name>
<url>http://dev.bukkit.org/bukkit-plugins/openinv/</url>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
<packaging>pom</packaging>
@@ -81,13 +81,13 @@
<artifactId>openinvapi</artifactId>
<groupId>com.lishid</groupId>
<scope>compile</scope>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</dependency>
<dependency>
<artifactId>openinvplugincore</artifactId>
<groupId>com.lishid</groupId>
<scope>compile</scope>
<version>4.1.8</version>
<version>4.1.9-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>