It's been over 3 years :)

The common module was designed to prevent the internal modules depending on the core plugin. With the introduction of localization, this overcomplication became ever more exacerbated.
Probably will play around a bit more to remove freshly introduced static abuse before release.
Closes #61
This commit is contained in:
Jikoo 2020-03-24 21:01:59 -04:00
parent c51acb4e72
commit c7b4554a6c
29 changed files with 530 additions and 218 deletions

View file

@ -43,23 +43,6 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</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>

View file

@ -34,7 +34,7 @@
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.0</version>
<executions>
<execution>
<id>reactor-uberjar</id>

View file

@ -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>openinvparent</artifactId>
<version>4.0.9-SNAPSHOT</version>
</parent>
<artifactId>openinvcommon</artifactId>
<name>OpenInvCommon</name>
<dependencies>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvapi</artifactId>
<version>4.0.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</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>

View file

@ -37,7 +37,7 @@
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<artifactId>openinvplugincore</artifactId>
<version>4.0.9-SNAPSHOT</version>
</dependency>
</dependencies>
@ -47,7 +47,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.2</version>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>

View file

@ -16,6 +16,7 @@
package com.lishid.openinv.internal.v1_14_R1;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.internal.IAnySilentContainer;
import java.lang.reflect.Field;
import net.minecraft.server.v1_14_R1.Block;
@ -191,7 +192,7 @@ public class AnySilentContainer implements IAnySilentContainer {
InventoryEnderChest enderChest = player.getEnderChest();
enderChest.a((TileEntityEnderChest) tile);
player.openContainer(new TileInventory((containerCounter, playerInventory, ignored) -> {
Containers containers;
Containers<?> containers;
int rows = enderChest.getSize() / 9;
switch (rows) {
case 1:
@ -300,7 +301,7 @@ public class AnySilentContainer implements IAnySilentContainer {
if (tile instanceof TileEntityLootable) {
TileEntityLootable lootable = (TileEntityLootable) tile;
if (lootable.lootTable != null) {
player.a(new ChatMessage("Loot not generated! Please disable /silentcontainer.").a(EnumChatFormat.RED), true);
OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated");
return false;
}
}

View file

@ -16,16 +16,19 @@
package com.lishid.openinv.internal.v1_14_R1;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.internal.IPlayerDataManager;
import com.lishid.openinv.internal.ISpecialInventory;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.v1_14_R1.ChatComponentText;
import net.minecraft.server.v1_14_R1.ChatMessageType;
import net.minecraft.server.v1_14_R1.Container;
import net.minecraft.server.v1_14_R1.Containers;
import net.minecraft.server.v1_14_R1.DimensionManager;
import net.minecraft.server.v1_14_R1.EntityHuman;
import net.minecraft.server.v1_14_R1.EntityPlayer;
import net.minecraft.server.v1_14_R1.MinecraftServer;
import net.minecraft.server.v1_14_R1.PacketPlayOutChat;
import net.minecraft.server.v1_14_R1.PacketPlayOutOpenWindow;
import net.minecraft.server.v1_14_R1.PlayerInteractManager;
import net.minecraft.server.v1_14_R1.PlayerInventory;
@ -42,9 +45,11 @@ 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 {
@NotNull
public static EntityPlayer getHandle(final Player player) {
if (player instanceof CraftPlayer) {
return ((CraftPlayer) player).getHandle();
@ -88,26 +93,37 @@ public class PlayerDataManager implements IPlayerDataManager {
return target;
}
@Nullable
@Override
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
EntityPlayer nmsPlayer = getHandle(player);
if (nmsPlayer == null || nmsPlayer.playerConnection == null) {
if (nmsPlayer.playerConnection == null) {
return null;
}
String title;
if (inventory instanceof SpecialEnderChest) {
HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner();
title = (owner.getName() != null ? owner.getName() : owner.getUniqueId().toString()) + "'s Ender Chest";
title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.enderchest");
if (title == null) {
title = "%player%'s Ender Chest";
}
//noinspection ConstantConditions - owner name can be null if loaded by UUID
title = title.replace("%player%", owner.getName() != null ? owner.getName() : owner.getUniqueId().toString());
} else if (inventory instanceof SpecialPlayerInventory) {
EntityHuman owner = ((PlayerInventory) inventory).player;
title = (owner.getName() != null ? owner.getName() : owner.getUniqueID().toString()) + "'s Inventory";
title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.player");
if (title == null) {
title = "%player%'s Inventory";
}
title = title.replace("%player%", owner.getName() != null ? owner.getName() : owner.getUniqueID().toString());
} else {
return player.openInventory(inventory.getBukkitInventory());
}
String finalTitle = title;
Container container = new CraftContainer(new InventoryView() {
@Override
public @NotNull Inventory getTopInventory() {
@ -127,7 +143,7 @@ public class PlayerDataManager implements IPlayerDataManager {
}
@Override
public @NotNull String getTitle() {
return title;
return finalTitle;
}
}, nmsPlayer, nmsPlayer.nextContainerCounter()) {
@Override
@ -167,4 +183,24 @@ public class PlayerDataManager implements IPlayerDataManager {
}
@Override
public void sendSystemMessage(@NotNull Player player, @NotNull String message) {
int newline = message.indexOf('\n');
if (newline != -1) {
// No newlines in action bar chat.
message = message.substring(0, newline);
}
if (message.isEmpty()) {
return;
}
EntityPlayer nmsPlayer = getHandle(player);
// For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text.
if (nmsPlayer.playerConnection != null) {
nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO));
}
}
}

View file

@ -37,7 +37,7 @@
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<artifactId>openinvplugincore</artifactId>
<version>4.0.9-SNAPSHOT</version>
</dependency>
</dependencies>
@ -47,7 +47,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.2</version>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>

View file

@ -16,6 +16,7 @@
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;
@ -300,7 +301,7 @@ public class AnySilentContainer implements IAnySilentContainer {
if (tile instanceof TileEntityLootable) {
TileEntityLootable lootable = (TileEntityLootable) tile;
if (lootable.lootTable != null) {
player.a(new ChatMessage("Loot not generated! Please disable /silentcontainer.").a(EnumChatFormat.RED), true);
OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated");
return false;
}
}

View file

@ -16,16 +16,19 @@
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 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.EntityHuman;
import net.minecraft.server.v1_15_R1.EntityPlayer;
import net.minecraft.server.v1_15_R1.MinecraftServer;
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;
@ -42,9 +45,11 @@ 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 {
@NotNull
public static EntityPlayer getHandle(final Player player) {
if (player instanceof CraftPlayer) {
return ((CraftPlayer) player).getHandle();
@ -65,6 +70,7 @@ public class PlayerDataManager implements IPlayerDataManager {
return nmsPlayer;
}
@Nullable
@Override
public Player loadPlayer(@NotNull final OfflinePlayer offline) {
// Ensure player has data
@ -88,26 +94,37 @@ public class PlayerDataManager implements IPlayerDataManager {
return target;
}
@Nullable
@Override
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
EntityPlayer nmsPlayer = getHandle(player);
if (nmsPlayer == null || nmsPlayer.playerConnection == null) {
if (nmsPlayer.playerConnection == null) {
return null;
}
String title;
if (inventory instanceof SpecialEnderChest) {
HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner();
title = (owner.getName() != null ? owner.getName() : owner.getUniqueId().toString()) + "'s Ender Chest";
title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.enderchest");
if (title == null) {
title = "%player%'s Ender Chest";
}
//noinspection ConstantConditions - owner name can be null if loaded by UUID
title = title.replace("%player%", owner.getName() != null ? owner.getName() : owner.getUniqueId().toString());
} else if (inventory instanceof SpecialPlayerInventory) {
EntityHuman owner = ((PlayerInventory) inventory).player;
title = (owner.getName() != null ? owner.getName() : owner.getUniqueID().toString()) + "'s Inventory";
title = OpenInv.getPlugin(OpenInv.class).getLocalizedMessage(player, "container.player");
if (title == null) {
title = "%player%'s Inventory";
}
title = title.replace("%player%", owner.getName() != null ? owner.getName() : owner.getUniqueID().toString());
} else {
return player.openInventory(inventory.getBukkitInventory());
}
String finalTitle = title;
Container container = new CraftContainer(new InventoryView() {
@Override
public @NotNull Inventory getTopInventory() {
@ -127,7 +144,7 @@ public class PlayerDataManager implements IPlayerDataManager {
}
@Override
public @NotNull String getTitle() {
return title;
return finalTitle;
}
}, nmsPlayer, nmsPlayer.nextContainerCounter()) {
@Override
@ -167,4 +184,24 @@ public class PlayerDataManager implements IPlayerDataManager {
}
@Override
public void sendSystemMessage(@NotNull Player player, @NotNull String message) {
int newline = message.indexOf('\n');
if (newline != -1) {
// No newlines in action bar chat.
message = message.substring(0, newline);
}
if (message.isEmpty()) {
return;
}
EntityPlayer nmsPlayer = getHandle(player);
// For action bar chat, color codes are still supported but JSON text color is not allowed. Do not convert text.
if (nmsPlayer.playerConnection != null) {
nmsPlayer.playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(message), ChatMessageType.GAME_INFO));
}
}
}

View file

@ -36,7 +36,7 @@
</dependency>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<artifactId>openinvplugincore</artifactId>
<version>4.0.9-SNAPSHOT</version>
</dependency>
</dependencies>
@ -46,7 +46,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.2</version>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>

View file

@ -19,8 +19,10 @@ 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 net.minecraft.server.v1_8_R3.ChatComponentText;
import net.minecraft.server.v1_8_R3.EntityPlayer;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import net.minecraft.server.v1_8_R3.PacketPlayOutChat;
import net.minecraft.server.v1_8_R3.PlayerInteractManager;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@ -30,9 +32,32 @@ 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 {
@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
@ -56,29 +81,36 @@ public class PlayerDataManager implements IPlayerDataManager {
return target;
}
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 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;
}
}

View file

@ -30,13 +30,13 @@
<dependencies>
<dependency>
<groupId>com.lishid</groupId>
<artifactId>openinvcommon</artifactId>
<artifactId>openinvapi</artifactId>
<version>4.0.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<version>1.15.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@ -52,7 +52,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.2</version>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>

View file

@ -35,6 +35,7 @@ import com.lishid.openinv.listeners.PluginListener;
import com.lishid.openinv.util.Cache;
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.HashMap;
import java.util.Iterator;
@ -45,6 +46,7 @@ import java.util.concurrent.Future;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.HumanEntity;
@ -107,6 +109,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
});
private InternalAccessor accessor;
private LanguageManager languageManager;
/**
* Evicts all viewers lacking cross-world permissions from a Player's inventory.
@ -128,8 +131,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
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() == null
|| human.getWorld().equals(player.getWorld())) {
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
continue;
}
human.closeInventory();
@ -140,8 +142,7 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
Iterator<HumanEntity> iterator = this.enderChests.get(key).getBukkitInventory().getViewers().iterator();
while (iterator.hasNext()) {
HumanEntity human = iterator.next();
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld() == null
|| human.getWorld().equals(player.getWorld())) {
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
continue;
}
human.closeInventory();
@ -284,6 +285,43 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
return this.accessor.getPlayerDataManager().openInventory(player, inventory);
}
public void sendMessage(@NotNull CommandSender sender, @NotNull String key) {
String message = this.languageManager.getValue(key, getLocale(sender));
if (message != null && !message.isEmpty()) {
sender.sendMessage(message);
}
}
public void sendMessage(@NotNull CommandSender sender, @NotNull String key, String... replacements) {
String message = this.languageManager.getValue(key, getLocale(sender), replacements);
if (message != null && !message.isEmpty()) {
sender.sendMessage(message);
}
}
public void sendSystemMessage(@NotNull Player player, @NotNull String key) {
String message = this.languageManager.getValue(key, getLocale(player));
if (message != null) {
this.accessor.getPlayerDataManager().sendSystemMessage(player, message);
}
}
public @Nullable String getLocalizedMessage(@NotNull CommandSender sender, @NotNull String key) {
return this.languageManager.getValue(key, getLocale(sender));
}
@Nullable
private String getLocale(@NotNull CommandSender sender) {
if (sender instanceof Player) {
return this.accessor.getPlayerDataManager().getLocale((Player) sender);
} else {
return this.getConfig().getString("settings.locale", "en_us");
}
}
@Override
public boolean notifyAnyChest() {
return this.getConfig().getBoolean("notify.any-chest", true);
@ -317,6 +355,8 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
this.accessor = new InternalAccessor(this);
this.languageManager = new LanguageManager(this, "en_us");
// Version check
if (this.accessor.isSupported()) {
// Update existing configuration. May require internal access.
@ -332,16 +372,16 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
// Register commands to their executors
OpenInvCommand openInv = new OpenInvCommand(this);
this.getCommand("openinv").setExecutor(openInv);
this.getCommand("openender").setExecutor(openInv);
this.setCommandExecutor("openinv", openInv);
this.setCommandExecutor("openender", openInv);
this.setCommandExecutor("searchcontainer", new SearchContainerCommand(this));
SearchInvCommand searchInv = new SearchInvCommand(this);
this.getCommand("searchcontainer").setExecutor(new SearchContainerCommand());
this.getCommand("searchinv").setExecutor(searchInv);
this.getCommand("searchender").setExecutor(searchInv);
this.getCommand("searchenchant").setExecutor(new SearchEnchantCommand(this));
this.setCommandExecutor("searchinv", searchInv);
this.setCommandExecutor("searchender", searchInv);
this.setCommandExecutor("searchenchant", new SearchEnchantCommand(this));
ContainerSettingCommand settingCommand = new ContainerSettingCommand(this);
this.getCommand("silentcontainer").setExecutor(settingCommand);
this.getCommand("anycontainer").setExecutor(settingCommand);
this.setCommandExecutor("silentcontainer", settingCommand);
this.setCommandExecutor("anycontainer", settingCommand);
} else {
this.getLogger().info("Your version of CraftBukkit (" + this.accessor.getVersion() + ") is not supported.");
@ -351,12 +391,18 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
}
private void setCommandExecutor(String commandName, CommandExecutor executor) {
PluginCommand command = this.getCommand(commandName);
if (command != null) {
command.setExecutor(executor);
}
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!this.accessor.isSupported()) {
sender.sendMessage("Your version of CraftBukkit (" + this.accessor.getVersion() + ") is not supported.");
sender.sendMessage("If this version is a recent release, check for an update.");
sender.sendMessage("If this is an older version, ensure that you've downloaded the legacy support version.");
return true;
}
return false;

View file

@ -22,12 +22,12 @@ import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ContainerSettingCommand implements TabExecutor {
@ -38,15 +38,14 @@ public class ContainerSettingCommand implements TabExecutor {
}
@Override
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
return true;
}
Player player = (Player) sender;
boolean any = command.getName().startsWith("any");
String commandName = any ? "AnyContainer" : "SilentContainer";
Function<Player, Boolean> getSetting = any ? plugin::getPlayerAnyChestStatus : plugin::getPlayerSilentChestStatus;
BiConsumer<OfflinePlayer, Boolean> setSetting = any ? plugin::setPlayerAnyChestStatus : plugin::setPlayerSilentChestStatus;
@ -66,13 +65,18 @@ public class ContainerSettingCommand implements TabExecutor {
setSetting.accept(player, !getSetting.apply(player));
}
sender.sendMessage(commandName + " is now " + (getSetting.apply(player) ? "ON" : "OFF") + ".");
String onOff = plugin.getLocalizedMessage(player, getSetting.apply(player) ? "messages.info.on" : "messages.info.off");
if (onOff == null) {
onOff = String.valueOf(getSetting.apply(player));
}
plugin.sendMessage(sender, "messages.info.settingState","%setting%", any ? "AnyContainer" : "SilentContainer", "%state%", onOff);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!command.testPermissionSilent(sender) || args.length != 1) {
return Collections.emptyList();
}

View file

@ -23,13 +23,13 @@ import com.lishid.openinv.util.TabCompleter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
public class OpenInvCommand implements TabExecutor {
@ -42,9 +42,9 @@ public class OpenInvCommand implements TabExecutor {
}
@Override
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
public boolean onCommand(@NotNull final CommandSender sender, @NotNull final Command command, @NotNull final String label, @NotNull final String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
return true;
}
@ -79,7 +79,7 @@ public class OpenInvCommand implements TabExecutor {
final OfflinePlayer offlinePlayer = OpenInvCommand.this.plugin.matchPlayer(name);
if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
player.sendMessage(ChatColor.RED + "Player not found!");
plugin.sendMessage(player, "messages.error.invalidPlayer");
return;
}
@ -100,49 +100,48 @@ public class OpenInvCommand implements TabExecutor {
}
private void openInventory(final Player player, final OfflinePlayer target, boolean openinv) {
Player onlineTarget;
boolean online = target.isOnline();
if (!online) {
// Try loading the player's data
onlineTarget = this.plugin.loadPlayer(target);
if (onlineTarget == null) {
player.sendMessage(ChatColor.RED + "Player not found!");
return;
}
} else {
onlineTarget = target.getPlayer();
}
if (onlineTarget == null) {
plugin.sendMessage(player, "messages.error.invalidPlayer");
return;
}
// Permissions checks
if (onlineTarget.equals(player)) {
// Inventory: Additional permission required to open own inventory
if (openinv && !Permissions.OPENSELF.hasPermission(player)) {
player.sendMessage(ChatColor.RED + "You're not allowed to open your own inventory!");
plugin.sendMessage(player, "messages.error.permissionOpenSelf");
return;
}
} else {
// Enderchest: Additional permission required to open others' ender chests
if (!openinv && !Permissions.ENDERCHEST_ALL.hasPermission(player)) {
player.sendMessage(ChatColor.RED + "You do not have permission to access other players' ender chests.");
plugin.sendMessage(player, "messages.error.permissionEnderAll");
return;
}
// Protected check
if (!Permissions.OVERRIDE.hasPermission(player)
&& Permissions.EXEMPT.hasPermission(onlineTarget)) {
player.sendMessage(ChatColor.RED + onlineTarget.getDisplayName() + "'s inventory is protected!");
plugin.sendMessage(player, "messages.error.permissionExempt",
"%target%", onlineTarget.getDisplayName());
return;
}
// Crossworld check
if (!Permissions.CROSSWORLD.hasPermission(player)
&& !onlineTarget.getWorld().equals(player.getWorld())) {
player.sendMessage(
ChatColor.RED + onlineTarget.getDisplayName() + " is not in your world!");
plugin.sendMessage(player, "messages.error.permissionCrossWorld",
"%target%", onlineTarget.getDisplayName());
return;
}
}
@ -155,7 +154,7 @@ public class OpenInvCommand implements TabExecutor {
try {
inv = openinv ? this.plugin.getSpecialInventory(onlineTarget, online) : this.plugin.getSpecialEnderChest(onlineTarget, online);
} catch (Exception e) {
player.sendMessage(ChatColor.RED + "An error occurred creating " + onlineTarget.getDisplayName() + "'s inventory!");
plugin.sendMessage(player, "messages.error.commandException");
e.printStackTrace();
return;
}
@ -165,7 +164,7 @@ public class OpenInvCommand implements TabExecutor {
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!command.testPermissionSilent(sender) || args.length != 1) {
return Collections.emptyList();
}

View file

@ -16,10 +16,10 @@
package com.lishid.openinv.commands;
import com.lishid.openinv.OpenInv;
import com.lishid.openinv.util.TabCompleter;
import java.util.Collections;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
@ -29,16 +29,23 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.InventoryHolder;
import org.jetbrains.annotations.NotNull;
/**
* Command for searching containers in a radius of chunks.
*/
public class SearchContainerCommand implements TabExecutor {
private final OpenInv plugin;
public SearchContainerCommand(OpenInv plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
return true;
}
@ -47,10 +54,10 @@ public class SearchContainerCommand implements TabExecutor {
return false;
}
Material material = Material.getMaterial(args[0]);
Material material = Material.getMaterial(args[0].toUpperCase());
if (material == null) {
sender.sendMessage(ChatColor.RED + "Unknown item: \"" + args[0] + "\"");
plugin.sendMessage(sender, "messages.error.invalidMaterial", "%target%", args[0]);
return false;
}
@ -95,15 +102,18 @@ public class SearchContainerCommand implements TabExecutor {
if (locations.length() > 0) {
locations.delete(locations.length() - 2, locations.length());
} else {
sender.sendMessage("No containers found with " + material.toString());
plugin.sendMessage(sender, "messages.info.container.noMatches",
"%target%", material.name());
return true;
}
sender.sendMessage("Containers holding item " + material.toString() + ": " + locations.toString());
plugin.sendMessage(sender, "messages.info.container.matches",
"%target%", material.name(), "%detail%", locations.toString());
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (args.length < 1 || args.length > 2 || !command.testPermissionSilent(sender)) {
return Collections.emptyList();
}

View file

@ -21,6 +21,7 @@ import com.lishid.openinv.util.TabCompleter;
import java.util.Collections;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@ -29,6 +30,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
/**
* Command adding the ability to search online players' inventories for enchantments of a specific
@ -45,7 +47,7 @@ public class SearchEnchantCommand implements TabExecutor {
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 0) {
return false;
}
@ -54,14 +56,28 @@ public class SearchEnchantCommand implements TabExecutor {
int level = 0;
for (String argument : args) {
Enchantment localEnchant = Enchantment.getByName(argument.toUpperCase());
if (localEnchant != null) {
enchant = localEnchant;
continue;
}
try {
level = Integer.parseInt(argument);
continue;
} catch (NumberFormatException ignored) {}
argument = argument.toLowerCase();
int colon = argument.indexOf(':');
NamespacedKey key;
try {
if (colon > -1 && colon < argument.length() - 1) {
key = new NamespacedKey(argument.substring(0, colon), argument.substring(colon + 1));
} else {
key = NamespacedKey.minecraft(argument);
}
} catch (IllegalArgumentException ignored) {
continue;
}
Enchantment localEnchant = Enchantment.getByKey(key);
if (localEnchant != null) {
enchant = localEnchant;
}
}
// Arguments not set correctly
@ -97,12 +113,14 @@ public class SearchEnchantCommand implements TabExecutor {
// Matches found, delete trailing comma and space
players.delete(players.length() - 2, players.length());
} else {
sender.sendMessage("No players found with " + (enchant == null ? "any enchant" : enchant.getName())
+ " of level " + level + " or higher.");
plugin.sendMessage(sender, "messages.info.player.noMatches",
"%target%", (enchant != null ? enchant.getKey().toString() : "") + " >= " + level);
return true;
}
sender.sendMessage("Players: " + players.toString());
plugin.sendMessage(sender, "messages.info.player.matches",
"%target%", (enchant != null ? enchant.getKey().toString() : "") + " >= " + level,
"%detail%", players.toString());
return true;
}
@ -120,7 +138,7 @@ public class SearchEnchantCommand implements TabExecutor {
continue;
}
ItemMeta meta = item.getItemMeta();
if (!meta.hasEnchants()) {
if (meta == null || !meta.hasEnchants()) {
continue;
}
for (int enchLevel : meta.getEnchants().values()) {
@ -134,13 +152,13 @@ public class SearchEnchantCommand implements TabExecutor {
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!command.testPermissionSilent(sender) || args.length < 1 || args.length > 2) {
return Collections.emptyList();
}
if (args.length == 1) {
return TabCompleter.completeObject(args[0], Enchantment::getName, Enchantment.values());
return TabCompleter.completeObject(args[0], enchantment -> enchantment.getKey().toString(), Enchantment.values());
} else {
return TabCompleter.completeInteger(args[1]);
}

View file

@ -20,13 +20,13 @@ import com.lishid.openinv.OpenInv;
import com.lishid.openinv.util.TabCompleter;
import java.util.Collections;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.NotNull;
public class SearchInvCommand implements TabExecutor {
@ -37,32 +37,33 @@ public class SearchInvCommand implements TabExecutor {
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Material material = null;
int count = 1;
if (args.length >= 1) {
material = Material.getMaterial(args[0]);
material = Material.getMaterial(args[0].toUpperCase());
}
if (args.length >= 2) {
try {
count = Integer.parseInt(args[1]);
} catch (NumberFormatException ex) {
sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!");
plugin.sendMessage(sender, "messages.error.invalidNumber", "%target%", args[1]);
return false;
}
}
if (material == null) {
sender.sendMessage(ChatColor.RED + "Unknown item: \"" + args[0] + "\"");
plugin.sendMessage(sender, "messages.error.invalidMaterial", "%target%", args[0]);
return false;
}
StringBuilder players = new StringBuilder();
boolean searchInv = command.getName().equals("searchinv");
for (Player player : plugin.getServer().getOnlinePlayers()) {
Inventory inventory = command.getName().equals("searchinv") ? player.getInventory() : player.getEnderChest();
Inventory inventory = searchInv ? player.getInventory() : player.getEnderChest();
if (inventory.contains(material, count)) {
players.append(player.getName()).append(", ");
}
@ -72,15 +73,18 @@ public class SearchInvCommand implements TabExecutor {
if (players.length() > 0) {
players.delete(players.length() - 2, players.length());
} else {
sender.sendMessage("No players found with " + material.toString());
plugin.sendMessage(sender, "messages.info.player.noMatches",
"%target%", material.name());
return true;
}
sender.sendMessage("Players with the item " + material.toString() + ": " + players.toString());
plugin.sendMessage(sender, "messages.info.player.matches",
"%target%", material.name(), "%detail%", players.toString());
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length < 1 || args.length > 2 || !command.testPermissionSilent(sender)) {
return Collections.emptyList();
}

View file

@ -32,7 +32,8 @@ public interface IPlayerDataManager {
* @param offline the OfflinePlayer
* @return the Player loaded
*/
@Nullable Player loadPlayer(@NotNull OfflinePlayer offline);
@Nullable
Player loadPlayer(@NotNull OfflinePlayer offline);
/**
* Opens an ISpecialInventory for a Player.
@ -42,6 +43,14 @@ public interface IPlayerDataManager {
*`
* @return the InventoryView opened
*/
@Nullable
InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory);
void sendSystemMessage(@NotNull Player player, @NotNull String message);
@NotNull
default String getLocale(Player player) {
return player.getLocale();
}
}

View file

@ -55,7 +55,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking()
|| event.useInteractedBlock() == Result.DENY
|| event.useInteractedBlock() == Result.DENY || event.getClickedBlock() == null
|| !plugin.getAnySilentContainer().isAnySilentContainer(event.getClickedBlock())) {
return;
}
@ -71,13 +71,15 @@ public class PlayerListener implements Listener {
boolean silent = Permissions.SILENT.hasPermission(player) && plugin.getPlayerSilentChestStatus(player);
// If anycontainer or silentcontainer is active
if ((any || silent) && plugin.getAnySilentContainer().activateContainer(player, silent, event.getClickedBlock())) {
if (any || silent) {
if (plugin.getAnySilentContainer().activateContainer(player, silent, event.getClickedBlock())) {
if (silent && plugin.notifySilentChest() && needsAny && plugin.notifyAnyChest()) {
player.sendMessage("You are opening a blocked container silently.");
} else if (silent && plugin.notifySilentChest()) {
player.sendMessage("You are opening a container silently.");
plugin.sendSystemMessage(player, "messages.info.containerBlockedSilent");
} else if (needsAny && plugin.notifyAnyChest()) {
player.sendMessage("You are opening a blocked container.");
plugin.sendSystemMessage(player, "messages.info.containerBlocked");
} else if (silent && plugin.notifySilentChest()) {
plugin.sendSystemMessage(player, "messages.info.containerSilent");
}
}
event.setCancelled(true);
}

View file

@ -59,6 +59,9 @@ public class ConfigUpdater {
if (version < 3) {
updateConfig2To3();
}
if (version < 4) {
updateConfig3To4();
}
new BukkitRunnable() {
@Override
@ -71,6 +74,17 @@ public class ConfigUpdater {
}.runTaskAsynchronously(plugin);
}
private void updateConfig3To4() {
new BukkitRunnable() {
@Override
public void run() {
plugin.getConfig().set("notify", null);
plugin.getConfig().set("settings.locale", "en_US");
plugin.getConfig().set("config-version", 4);
}
}.runTask(plugin);
}
private void updateConfig2To3() {
new BukkitRunnable() {
@Override

View file

@ -0,0 +1,165 @@
/*
* Copyright (C) 2011-2020 Jikoo. 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.util;
import com.lishid.openinv.OpenInv;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A simple language manager supporting both custom and bundled languages.
*
* @author Jikoo
*/
public class LanguageManager {
private final OpenInv plugin;
private final String defaultLocale;
private Map<String, YamlConfiguration> locales;
public LanguageManager(@NotNull OpenInv plugin, @NotNull String defaultLocale) {
this.plugin = plugin;
this.defaultLocale = defaultLocale;
this.locales = new HashMap<>();
getOrLoadLocale(defaultLocale);
}
private YamlConfiguration getOrLoadLocale(@NotNull String locale) {
YamlConfiguration loaded = locales.get(locale);
if (loaded != null) {
return loaded;
}
InputStream resourceStream = plugin.getResource(locale + ".yml");
YamlConfiguration localeConfigDefaults;
if (resourceStream == null) {
localeConfigDefaults = new YamlConfiguration();
} else {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceStream))) {
localeConfigDefaults = YamlConfiguration.loadConfiguration(reader);
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Unable to load resource " + locale + ".yml", e);
localeConfigDefaults = new YamlConfiguration();
}
}
File file = new File(plugin.getDataFolder(), locale + ".yml");
YamlConfiguration localeConfig;
if (!file.exists()) {
localeConfig = localeConfigDefaults;
try {
localeConfigDefaults.save(file);
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Unable to save resource " + locale + ".yml", e);
}
} else {
localeConfig = YamlConfiguration.loadConfiguration(file);
// Add new language keys
List<String> newKeys = new ArrayList<>();
for (String key : localeConfigDefaults.getKeys(true)) {
if (localeConfigDefaults.isConfigurationSection(key)) {
continue;
}
if (localeConfig.isSet(key)) {
continue;
}
localeConfig.set(key, localeConfigDefaults.get(key));
newKeys.add(key);
}
if (!newKeys.isEmpty()) {
plugin.getLogger().info("[LanguageManager] Added new language keys: " + String.join(", ", newKeys));
}
}
if (!locale.equals(defaultLocale)) {
localeConfigDefaults = locales.get(defaultLocale);
// Check for missing keys
List<String> newKeys = new ArrayList<>();
for (String key : localeConfigDefaults.getKeys(true)) {
if (localeConfigDefaults.isConfigurationSection(key)) {
continue;
}
if (localeConfig.isSet(key)) {
continue;
}
newKeys.add(key);
}
if (!newKeys.isEmpty()) {
plugin.getLogger().info("[LanguageManager] Missing translations from " + locale + ".yml: " + String.join(", ", newKeys));
}
// Fall through to default locale
localeConfig.setDefaults(localeConfigDefaults);
}
locales.put(locale, localeConfig);
return localeConfig;
}
@Nullable
public String getValue(@NotNull String key, @Nullable String locale) {
String value = getOrLoadLocale(locale == null ? defaultLocale : locale.toLowerCase()).getString(key);
if (value == null || value.isEmpty()) {
return null;
}
value = ChatColor.translateAlternateColorCodes('&', value);
return value;
}
@Nullable
public String getValue(@NotNull String key, @Nullable String locale, @NotNull String... replacements) {
if (replacements.length % 2 != 0) {
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Replacement data is uneven", new Exception());
}
String value = getValue(key, locale);
if (value == null) {
return null;
}
for (int i = 0; i < replacements.length; i += 2) {
value = value.replace(replacements[i], replacements[i + 1]);
}
return value;
}
}

View file

@ -1,6 +1,4 @@
config-version: 3
notify:
any-chest: true
silent-chest: true
config-version: 4
settings:
disable-saving: false
locale: 'en_us'

View file

@ -0,0 +1,28 @@
messages:
error:
consoleUnsupported: 'You cannot use this command from console.'
lootNotGenerated: '&cLoot not generated! Please disable &b/silentcontainer&c.'
invalidMaterial: '&cInvalid material: "%target%"'
invalidNumber: '&cInvalid number: "%target%"'
invalidPlayer: '&cPlayer not found!'
permissionOpenSelf: '&cYou''re not allowed to open your own inventory.'
permissionEnderAll: '&cYou''re not allowed to access other players'' ender chests.'
permissionExempt: '&c%target%''s inventory is protected.'
permissionCrossWorld: '&c%target% is not in your world.'
commandException: '&cAn error occurred. Please check console for details.'
info:
containerBlocked: 'You are opening a blocked container.'
containerBlockedSilent: 'You are opening a blocked container silently.'
containerSilent: 'You are opening a container silently.'
settingState: '%setting%: %state%'
player:
noMatches: 'No players found with %target%.'
matches: 'Players holding %target%: %detail%'
container:
noMatches: 'No containers found with %target%.'
matches: 'Containers holding %target%: %detail%'
on: 'on'
off: 'off'
container:
player: '%player%''s Inventory'
enderchest: '%Player''s Ender Chest'

View file

@ -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.13"
api-version: "1.14"
permissions:
OpenInv.any.default:
@ -24,7 +24,7 @@ permissions:
OpenInv.silent: true
OpenInv.anychest: true
OpenInv.searchenchant: true
OpenInv.searchcontainer
OpenInv.searchcontainer: true
commands:
openinv:

View file

@ -31,7 +31,6 @@
<modules>
<module>api</module>
<module>common</module>
<module>plugin</module>
<module>internal</module>
<module>assembly</module>