mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-01-09 09:57:40 +01:00
Release 1.17.3 (#1827)
* Version 1.17.1 * Add homes command to default player options. * Implements better online player counter. (#1791) Current one is based on online player count when bStats sends data to the server. This one will send data about amount of players who logged in the server. * Add Boxed Gamemode to the list. (#1793) * Add Bank addon (#1792) * Add Holographic Displays as SoftDepend for AOneBlock (#1794) * Custom date time format support for /<admin> info <player> (#1783) Fixes #1720 * Parent/sub-flag support, split up and designate CONTAINER flag as parent flag (#1784) * Split CONTAINER flag into multiple flags CONTAINER split into - CONTAINER (Chest/Minecart Chest) - BARREL (Barrel) - COMPOSTER (Composter) - FLOWER_POT (Flower Pot) - SHULKER_BOX (Shulker Box) - TRAPPED_CHEST (Trapped Chest) Fixes #1777 * Add subflag support * Create container parent flag, chest subflag * Remove extra string from when CHEST was CONTAINER * Fix incorrect flag specified on fired event in IslandToggleClick * Add missing world subflag event firing * Remove extra import * Add world setting flag for island visitors keep inventory (#1785) * Implement 3 bar charts: addons, gamemodes, hooks (#1790) BStats supports sending Bar chart data, however, it does not display it via their site directly. It can be called manually, to view. PieChart does not work very well for addons and hooks. BarChart however allows viewing each addon separately. This change allows sending data to the server about bar charts. * Update action versions * Declare distribution - adopt * Cache Java Maven files differently. * Try dependency for shade snapshot * Add support for Minecraft 1.17.1 * Fix test by incrementing listener value check There is a new listener now. * Spigot 1.17.1 * Fix test for InventoryListener * Re-order repos. * Downgrading to 1.17 Spigot for now to enable building. * Try pluginRespositories tag in POM to enable Github actions * Version 1.17.2 * Add alternative Addon#getIslandManager method (#1797) We have already done this to the main BentoBox class. But add-ons missed it, and it still has this weird structure: Addon#getIslands().getIslands(). This will just add the same method as it is already in BentoBox class. * Fix bucket dupe (#1806) Fix https://discord.com/channels/272499714048524288/310623455462686720/867790395442462760 * Removes unneeded exploit protection code for skulls (#1810) This no longer seems to be required with 1.17.1 https://github.com/BentoBoxWorld/BSkyBlock/issues/430 * Quote filename of addon that cannot be loaded. Provides a better understanding of which addon failed. * Remove update when pasting chest. * Version 1.17.3 * Java upgrade (#1814) * Version 1.17.3 * Use Map.of and List.of instead of Immutable collections * Replace explicit type argument. * Replace lamba with method reference * Replace condition with Objects.requireNonNullElseGet * Use String.repeat * Use new switch expressions * Use instanceof patten variables which are more compact * Fuse toUnmodifiableList into stream and return it. * Remove unnecessary toString() calls. * Remove unnecessary public * Extracted common part from if * Simplify conditional expressions * Remove unused IOExceptions * Cast to long * Use Map.putAll * Use primitives * Clarify what is null or not * Addedd @Serial annotation introduced with Java 14. * Use Optional.isEmpty instead of !isPresent * Use flatMap then ifPresent * Just use Arrays.stream * Swap map and filter for null with Objects::nonNull * Use expression lambda * Update JavaDoc version to 16 * Make spawn protection area square instead of circle. https://github.com/BentoBoxWorld/BentoBox/issues/1819 * Improve ItemParser code. (#1821) * Improve ItemParser code. Add ability to parse text if Material is just a single string. Add ability to parse player heads. Add comments to the code. * Fixes failing test. * Added deprecation suppression. * Added Pladdon to loadbefore. * Prevent bucket duping when scooping obsidian Part 35 https://github.com/BentoBoxWorld/BentoBox/issues/1825 * Warns visitors that PVP is active if they teleport to an island https://github.com/BentoBoxWorld/BentoBox/issues/1780 * Prevents repeated portaling when nether is disabled. (#1826) * Prevents repeated portaling when nether is disabled. https://github.com/BentoBoxWorld/BentoBox/issues/1782 * Fix test * Hex pr 1820 (#1822) * Fix @since for subflags. (#1831) * Add Citizens to Softdepend list for NPC support (#1834) * Fix color test. * Set the default game mode when player makes island. * Corrects JavaDocs link Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1838 * Update to 3.3.1-SNAPSHOT for shade plugin. * Package info files for better JavaDocs (#1839) * Added package info files for better JavaDocs * Implement Flag icon changing via Locales file. (#1829) This commit contains 2 changes: - An option for Flag to use icon that is defined in locales after "icon" string. - An option for ItemParser to parse icon or return given value, if parsing was not successful. The flag option is not ideal, but it is simpler and easier to maintain then adding new config section where icons can be changed, as the locales file already contains a lot of info about each flag. * Support glowing ink in blueprints (#1842) Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1837 * Panel template (#1841) * Implement basic functionality to read data from template panels. Create TemplateReader class that has static method which generates a PanelTemplateRecord. This record contains every necessary information from user created template file so everyone could use it to generate a functional panel. These classes are just for reading templates and do not create actual panel. * Add template clearing via bentobox reload command. * Fix version command to show addon state. * Fix German flag banner description. Added more debug around error reporting. * Make variables final if they can be. (#1843) * Make variables final if they can be. * Do not use final so that test can pass. For testing, we use a trick to set this variable, but it won't work if it is final. Right now, I'd like to keep the test. * Static code analysis (#1844) * StringBuffer (Java 5) may be declared as StringBuilder * Replace map with flatMap * Use instanceof naming * No need to specify paramter types. * Remove verbose code * Fix JavaDoc issues * Make internal class a record. * Remove unused import. * Make internal class a record. * Made internal class a record. * Removed unused import * Fix typos * Fix typo in test. * Prevent home teleport when already home teleporting Home teleporting is async so it's possible to issue the command multiple times. This puts a flag in so that if a playeer is mid-teleport, then issuing the go command will just repeat the text that the player is teleporting home. https://github.com/BentoBoxWorld/BentoBox/issues/1637 * Extracted island info from the Island object. This is in preparation to have a different info for players than admins. https://github.com/BentoBoxWorld/BentoBox/issues/1501 * Slimmer trimmer island info for players. https://github.com/BentoBoxWorld/BentoBox/issues/1501 * Fixes coop and trust invites when team invites are not allowed If a member or sub-owner has coop or trust invite capability and not team invite rank, and confirm invites is on, then the invites were not working. Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1452 * Remove invulnerable visitor protection if island is in PVP mode We now have alerts if a player teleports to a PVP island. https://github.com/BentoBoxWorld/BentoBox/issues/668 * Fixes NPE in admin tp if nether or end worlds don't exist. * Adds arrow sound when teleporting into a PVP island. * Fix PVPListenerTest Visitors are no longer invincible when on a PVP island. * Fix test failure in InvincibleVisitorsListenerTest * Minor JavaDoc correction. * Go command was not working second time. * Prevents console errors for missing icons in locale files. * Fixes PlAddon disabling issue. (#1847) There was a bug that did not unload PlAddon classes from JVM. This change should fix it, as it will unload PlAddons via pluginLoader. * Clear code - set worlds once on construction. * Fixes a bug when Potion metadata was not applied (#1849) There was missing potion meta data applying after creating an item. This affects both: Potions and Tipped arrows. * Adds force-shown lines to the template. (#1850) * Adds force-shown lines to the template. Fixes a bug when template type was not selected correctly. Changes "name" to "title" for border and background icons. * Create TemplatedPanel and TemplatedPanelBuilder. TemplatedPanel uses PanelTemplateRecord to create a functional panel. Builder contains button builder callbacks that are used to create buttons with custom data. * Use final vars for lambdas to avoid them changing async The processes could run async, especially when chunk loading took a while, so using fields that could change would result in blocks being missed, especially in the nether or end. Switching to final vars avoids this. Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1840 * Remove travis. Co-authored-by: BONNe <bonne@bonne.id.lv> Co-authored-by: Fredthedoggy <45927799+Fredthedoggy@users.noreply.github.com> Co-authored-by: Justin <jstnf@users.noreply.github.com> Co-authored-by: gecko10000 <60494179+levtey@users.noreply.github.com>
This commit is contained in:
parent
1a7b7cdeb7
commit
a6d70d6e90
23
.travis.yml
23
.travis.yml
@ -1,23 +0,0 @@
|
||||
language: java
|
||||
sudo: false
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "bentobox-world"
|
||||
|
||||
jdk:
|
||||
- openjdk8
|
||||
- openjdk11
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- jdk: openjdk11
|
||||
|
||||
script:
|
||||
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install
|
||||
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh && . ./install-jdk.sh -F 11 -L GPL
|
||||
- mvn sonar:sonar -Dsonar.projectKey=BentoBoxWorld_BentoBox
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- '$HOME/.sonar/cache'
|
@ -38,7 +38,7 @@ There are also plenty of other official or community-made Addons you can try and
|
||||
## Documentation
|
||||
|
||||
* Start reading: [https://docs.bentobox.world](https://docs.bentobox.world)
|
||||
* For developers: [Javadocs](https://bentoboxworld.github.io/BentoBox/)
|
||||
* For developers: [Javadocs](https://ci.codemc.io/job/BentoBoxWorld/job/BentoBox/ws/target/apidocs/index.html)
|
||||
|
||||
## Downloads
|
||||
|
||||
|
6
pom.xml
6
pom.xml
@ -83,7 +83,7 @@
|
||||
<!-- Do not change unless you want different name for local builds. -->
|
||||
<build.number>-LOCAL</build.number>
|
||||
<!-- This allows to change between versions. -->
|
||||
<build.version>1.17.2</build.version>
|
||||
<build.version>1.17.3</build.version>
|
||||
</properties>
|
||||
|
||||
<!-- Profiles will allow to automatically change build version. -->
|
||||
@ -353,7 +353,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<source>16</source>
|
||||
<show>private</show>
|
||||
<failOnError>false</failOnError>
|
||||
<additionalJOption>-Xdoclint:none</additionalJOption>
|
||||
@ -387,7 +387,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<relocations>
|
||||
|
@ -263,7 +263,7 @@ public class BentoBox extends JavaPlugin {
|
||||
}
|
||||
|
||||
private void fireCriticalError(String message, String error) {
|
||||
logError("*****************CRITIAL ERROR!******************");
|
||||
logError("*****************CRITICAL ERROR!******************");
|
||||
logError(message);
|
||||
logError(error + " Disabling BentoBox...");
|
||||
logError("*************************************************");
|
||||
|
@ -40,7 +40,7 @@ public abstract class Addon {
|
||||
private FileConfiguration config;
|
||||
private File dataFolder;
|
||||
private File file;
|
||||
private Map<String, AddonRequestHandler> requestHandlers = new HashMap<>();
|
||||
private final Map<String, AddonRequestHandler> requestHandlers = new HashMap<>();
|
||||
|
||||
protected Addon() {
|
||||
state = State.DISABLED;
|
||||
|
@ -30,8 +30,8 @@ import world.bentobox.bentobox.managers.AddonsManager;
|
||||
public class AddonClassLoader extends URLClassLoader {
|
||||
|
||||
private final Map<String, Class<?>> classes = new HashMap<>();
|
||||
private Addon addon;
|
||||
private AddonsManager loader;
|
||||
private final Addon addon;
|
||||
private final AddonsManager loader;
|
||||
|
||||
public AddonClassLoader(AddonsManager addonsManager, YamlConfiguration data, File jarFile, ClassLoader parent)
|
||||
throws InvalidAddonInheritException,
|
||||
|
@ -163,9 +163,12 @@ public final class AddonDescription {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private @NonNull String main;
|
||||
private @NonNull String name;
|
||||
private @NonNull String version;
|
||||
private @NonNull
|
||||
final String main;
|
||||
private @NonNull
|
||||
final String name;
|
||||
private @NonNull
|
||||
final String version;
|
||||
private @NonNull String description = "";
|
||||
private @NonNull List<String> authors = new ArrayList<>();
|
||||
private @NonNull List<String> dependencies = new ArrayList<>();
|
||||
|
@ -54,4 +54,13 @@ public abstract class Pladdon extends JavaPlugin {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method enables marks pladdons as enabled.
|
||||
* By default, enable status is not set because onEnable and onLoad is not triggered.
|
||||
*/
|
||||
public void setEnabled() {
|
||||
this.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public abstract class AddonException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4203162022348693854L;
|
||||
|
||||
protected AddonException(String errorMessage){
|
||||
|
@ -1,8 +1,11 @@
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class AddonRequestException extends AddonException
|
||||
{
|
||||
private static final long serialVersionUID = -5698456013070166174L;
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5698456013070166174L;
|
||||
|
||||
public AddonRequestException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
|
@ -1,5 +1,7 @@
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* @since 1.11.0
|
||||
*/
|
||||
@ -8,6 +10,7 @@ public class InvalidAddonDescriptionException extends AddonException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 7741502900847049986L;
|
||||
|
||||
public InvalidAddonDescriptionException(String errorMessage) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -9,6 +10,7 @@ public class InvalidAddonFormatException extends AddonException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 7741502900847049986L;
|
||||
|
||||
public InvalidAddonFormatException(String errorMessage) {
|
||||
|
@ -1,10 +1,13 @@
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class InvalidAddonInheritException extends AddonException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5847358994397613244L;
|
||||
|
||||
public InvalidAddonInheritException(String errorMessage) {
|
||||
|
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* This package covers Addon exceptions
|
||||
* <p>
|
||||
* These exceptions can be thrown when the addon is loaded.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
* @author tastybento
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* This package covers all addon-specific API
|
||||
* <p>
|
||||
* The Addon class and the associated Pladdon are like Bukkit plugins
|
||||
* but contain extra API specific for BentoBox games.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons;
|
@ -20,7 +20,7 @@ public class AddonRequestBuilder
|
||||
{
|
||||
private String addonName;
|
||||
private String requestLabel;
|
||||
private Map<String, Object> metaData = new HashMap<>();
|
||||
private final Map<String, Object> metaData = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Define the addon you wish to request.
|
||||
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* API to enable plugins to request data from addons.
|
||||
* <p>
|
||||
* Addons can expose data that they want to expose. To access it, call this class with the appropriate addon name,
|
||||
* the label for the data that is requested and if required, a map of key-value pairs that will be given to the addon.
|
||||
*
|
||||
* <b>Note</b> Since BentoBox 1.17.0, Addons can be declared as Pladdons and be loaded by the Bukkit classloader. This
|
||||
* enables Plugins to access Addon methods directly so this API is not required.
|
||||
* </p>
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons.request;
|
@ -33,7 +33,7 @@ import world.bentobox.bentobox.managers.PlayersManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* BSB composite command
|
||||
* BentoBox composite command. Provides an abstract implementation of a command.
|
||||
* @author tastybento
|
||||
* @author Poslovitch
|
||||
*/
|
||||
@ -78,12 +78,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
/**
|
||||
* Map of sub commands
|
||||
*/
|
||||
private Map<String, CompositeCommand> subCommands;
|
||||
private final Map<String, CompositeCommand> subCommands;
|
||||
|
||||
/**
|
||||
* Map of aliases for subcommands
|
||||
*/
|
||||
private Map<String, CompositeCommand> subCommandAliases;
|
||||
private final Map<String, CompositeCommand> subCommandAliases;
|
||||
/**
|
||||
* The command chain from the very top, e.g., island team promote
|
||||
*/
|
||||
@ -93,7 +93,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
* The prefix to be used in this command
|
||||
*/
|
||||
@Nullable
|
||||
private String permissionPrefix;
|
||||
private final String permissionPrefix;
|
||||
|
||||
/**
|
||||
* The world that this command operates in. This is an overworld and will cover any associated nether or end
|
||||
@ -104,17 +104,17 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
/**
|
||||
* The addon creating this command, if any
|
||||
*/
|
||||
private Addon addon;
|
||||
private final Addon addon;
|
||||
|
||||
/**
|
||||
* The top level label
|
||||
*/
|
||||
private String topLabel;
|
||||
private final String topLabel;
|
||||
|
||||
/**
|
||||
* Cool down tracker
|
||||
*/
|
||||
private Map<String, Map<String, Long>> cooldowns = new HashMap<>();
|
||||
private final Map<String, Map<String, Long>> cooldowns = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Top level command
|
||||
@ -144,7 +144,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
// Run setup
|
||||
setup();
|
||||
if (!getSubCommand("help").isPresent() && !label.equals("help")) {
|
||||
if (getSubCommand("help").isEmpty() && !label.equals("help")) {
|
||||
new DefaultHelpCommand(this);
|
||||
}
|
||||
}
|
||||
@ -204,11 +204,11 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
p = p.getParent();
|
||||
index++;
|
||||
}
|
||||
setDescription(COMMANDS + reference.toString() + ".description");
|
||||
setParametersHelp(COMMANDS + reference.toString() + ".parameters");
|
||||
setDescription(COMMANDS + reference + ".description");
|
||||
setParametersHelp(COMMANDS + reference + ".parameters");
|
||||
setup();
|
||||
// If this command does not define its own help class, then use the default help command
|
||||
if (!getSubCommand("help").isPresent() && !label.equals("help")) {
|
||||
if (getSubCommand("help").isEmpty() && !label.equals("help")) {
|
||||
new DefaultHelpCommand(this);
|
||||
}
|
||||
}
|
||||
@ -278,7 +278,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
// get the subcommand corresponding to the arg
|
||||
if (subCommand.hasSubCommands()) {
|
||||
Optional<CompositeCommand> sub = subCommand.getSubCommand(arg);
|
||||
if (!sub.isPresent()) {
|
||||
if (sub.isEmpty()) {
|
||||
return subCommand;
|
||||
}
|
||||
// Step down one
|
||||
@ -602,7 +602,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
return options;
|
||||
}
|
||||
// Add any tab completion from the subcommand
|
||||
options.addAll(command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args))).orElseGet(() -> new ArrayList<>()));
|
||||
options.addAll(command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args))).orElseGet(ArrayList::new));
|
||||
if (command.hasSubCommands()) {
|
||||
options.addAll(getSubCommandLabels(sender, command));
|
||||
}
|
||||
@ -701,7 +701,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public void setCooldown(String uniqueId, String targetUUID, int timeInSeconds) {
|
||||
cooldowns.computeIfAbsent(uniqueId, k -> new HashMap<>()).put(targetUUID, System.currentTimeMillis() + timeInSeconds * 1000);
|
||||
cooldowns.computeIfAbsent(uniqueId, k -> new HashMap<>()).put(targetUUID, System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -711,7 +711,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
* @param timeInSeconds - time in seconds to cool down
|
||||
*/
|
||||
public void setCooldown(UUID uniqueId, UUID targetUUID, int timeInSeconds) {
|
||||
cooldowns.computeIfAbsent(uniqueId.toString(), k -> new HashMap<>()).put(targetUUID == null ? null : targetUUID.toString(), System.currentTimeMillis() + timeInSeconds * 1000);
|
||||
cooldowns.computeIfAbsent(uniqueId.toString(), k -> new HashMap<>()).put(targetUUID == null ? null : targetUUID.toString(), System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
||||
/**
|
||||
* Confirmation tracker
|
||||
*/
|
||||
private static Map<User, Confirmer> toBeConfirmed = new HashMap<>();
|
||||
private static final Map<User, Confirmer> toBeConfirmed = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Top level command
|
||||
@ -61,9 +61,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
||||
public void askConfirmation(User user, String message, Runnable confirmed) {
|
||||
// Check for pending confirmations
|
||||
if (toBeConfirmed.containsKey(user)) {
|
||||
if (toBeConfirmed.get(user).getTopLabel().equals(getTopLabel()) && toBeConfirmed.get(user).getLabel().equalsIgnoreCase(getLabel())) {
|
||||
toBeConfirmed.get(user).getTask().cancel();
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).getRunnable());
|
||||
if (toBeConfirmed.get(user).topLabel().equals(getTopLabel()) && toBeConfirmed.get(user).label().equalsIgnoreCase(getLabel())) {
|
||||
toBeConfirmed.get(user).task().cancel();
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).runnable());
|
||||
toBeConfirmed.remove(user);
|
||||
return;
|
||||
} else {
|
||||
@ -97,51 +97,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the data to run once the confirmation is given
|
||||
* @author tastybento
|
||||
* Record to hold the data to run once the confirmation is given
|
||||
*
|
||||
*/
|
||||
private class Confirmer {
|
||||
private final String topLabel;
|
||||
private final String label;
|
||||
private final Runnable runnable;
|
||||
private final BukkitTask task;
|
||||
|
||||
/**
|
||||
* @param label - command label
|
||||
* @param runnable - runnable to run when confirmed
|
||||
* @param task - task ID to cancel when confirmed
|
||||
*/
|
||||
Confirmer(String topLabel, String label, Runnable runnable, BukkitTask task) {
|
||||
this.topLabel = topLabel;
|
||||
this.label = label;
|
||||
this.runnable = runnable;
|
||||
this.task = task;
|
||||
}
|
||||
/**
|
||||
* @return the topLabel
|
||||
*/
|
||||
public String getTopLabel() {
|
||||
return topLabel;
|
||||
}
|
||||
/**
|
||||
* @return the label
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
/**
|
||||
* @return the runnable
|
||||
*/
|
||||
public Runnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
/**
|
||||
* @return the task
|
||||
*/
|
||||
public BukkitTask getTask() {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
private record Confirmer (String topLabel, String label, Runnable runnable, BukkitTask task) { }
|
||||
|
||||
}
|
||||
|
@ -26,20 +26,20 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
||||
/**
|
||||
* User monitor map
|
||||
*/
|
||||
private static Map<UUID, DelayedCommand> toBeMonitored = new HashMap<>();
|
||||
private static final Map<UUID, DelayedCommand> toBeMonitored = new HashMap<>();
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerMove(PlayerMoveEvent e) {
|
||||
UUID uuid = e.getPlayer().getUniqueId();
|
||||
// Only check x,y,z
|
||||
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).getLocation().toVector())) {
|
||||
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).location().toVector())) {
|
||||
moved(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void moved(UUID uuid) {
|
||||
// Player moved
|
||||
toBeMonitored.get(uuid).getTask().cancel();
|
||||
toBeMonitored.get(uuid).task().cancel();
|
||||
toBeMonitored.remove(uuid);
|
||||
// Player has another outstanding confirmation request that will now be cancelled
|
||||
User.getInstance(uuid).notify("commands.delay.moved-so-command-cancelled");
|
||||
@ -103,7 +103,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
||||
UUID uuid = user.getUniqueId();
|
||||
if (toBeMonitored.containsKey(uuid)) {
|
||||
// A double request - clear out the old one
|
||||
toBeMonitored.get(uuid).getTask().cancel();
|
||||
toBeMonitored.get(uuid).task().cancel();
|
||||
toBeMonitored.remove(uuid);
|
||||
// Player has another outstanding confirmation request that will now be cancelled
|
||||
user.sendMessage("commands.delay.previous-command-cancelled");
|
||||
@ -116,7 +116,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
||||
user.sendMessage("commands.delay.stand-still", "[seconds]", String.valueOf(getSettings().getDelayTime()));
|
||||
// Set up the run task
|
||||
BukkitTask task = Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).getRunnable());
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).runnable());
|
||||
toBeMonitored.remove(uuid);
|
||||
}, getPlugin().getSettings().getDelayTime() * 20L);
|
||||
|
||||
@ -135,42 +135,8 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
||||
|
||||
/**
|
||||
* Holds the data to run once the confirmation is given
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
private class DelayedCommand {
|
||||
private final Runnable runnable;
|
||||
private final BukkitTask task;
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* @param runnable - runnable to run when confirmed
|
||||
* @param task - task ID to cancel when confirmed
|
||||
* @param location - location
|
||||
*/
|
||||
DelayedCommand(Runnable runnable, BukkitTask task, Location location) {
|
||||
this.runnable = runnable;
|
||||
this.task = task;
|
||||
this.location = location;
|
||||
}
|
||||
/**
|
||||
* @return the runnable
|
||||
*/
|
||||
public Runnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
/**
|
||||
* @return the task
|
||||
*/
|
||||
public BukkitTask getTask() {
|
||||
return task;
|
||||
}
|
||||
/**
|
||||
* @return the location
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
private record DelayedCommand(Runnable runnable, BukkitTask task, Location location) {}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminInfoCommand extends CompositeCommand {
|
||||
@ -34,10 +35,8 @@ public class AdminInfoCommand extends CompositeCommand {
|
||||
}
|
||||
// If there are no args, then the player wants info on the island at this location
|
||||
if (args.isEmpty()) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.showInfo(user)).orElse(false)) {
|
||||
user.sendMessage("commands.admin.info.no-island");
|
||||
return false;
|
||||
}
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user), () ->
|
||||
user.sendMessage("commands.admin.info.no-island"));
|
||||
return true;
|
||||
}
|
||||
// Get target player
|
||||
@ -49,7 +48,7 @@ public class AdminInfoCommand extends CompositeCommand {
|
||||
// Show info for this player
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (island != null) {
|
||||
island.showInfo(user);
|
||||
new IslandInfo(island).showAdminInfo(user);
|
||||
if (!getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID).isEmpty()) {
|
||||
user.sendMessage("commands.admin.info.islands-in-trash");
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class AdminResetFlagsCommand extends ConfirmableCommand {
|
||||
|
||||
private List<String> options;
|
||||
private final List<String> options;
|
||||
|
||||
public AdminResetFlagsCommand(CompositeCommand parent) {
|
||||
super(parent, "resetflags");
|
||||
|
@ -59,7 +59,7 @@ public class AdminSetProtectionCenterCommand extends ConfirmableCommand
|
||||
return false;
|
||||
}
|
||||
Optional<Island> optionalIsland = getIslands().getIslandAt(targetLoc);
|
||||
if (!optionalIsland.isPresent()) {
|
||||
if (optionalIsland.isEmpty()) {
|
||||
user.sendMessage("commands.admin.setspawnpoint.no-island-here");
|
||||
return false;
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
private final List<String> PROTECTION_FLAG_NAMES;
|
||||
private Island island;
|
||||
private final List<String> SETTING_FLAG_NAMES;
|
||||
private List<String> WORLD_SETTING_FLAG_NAMES;
|
||||
private @NonNull Optional<Flag> flag;
|
||||
private final List<String> WORLD_SETTING_FLAG_NAMES;
|
||||
private @NonNull Optional<Flag> flag = Optional.empty();
|
||||
private boolean activeState;
|
||||
private int rank;
|
||||
|
||||
@ -258,20 +258,14 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
}
|
||||
} else if (args.size() == 4) {
|
||||
// Get flag in previous argument
|
||||
options = getPlugin().getFlagsManager().getFlag(args.get(2).toUpperCase(Locale.ENGLISH)).map(f -> {
|
||||
switch (f.getType()) {
|
||||
case PROTECTION:
|
||||
return getPlugin().getRanksManager()
|
||||
.getRanks().entrySet().stream()
|
||||
.filter(en -> en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK)
|
||||
.map(Entry::getKey)
|
||||
.map(user::getTranslation).collect(Collectors.toList());
|
||||
case SETTING:
|
||||
return Arrays.asList(active, disabled);
|
||||
default:
|
||||
return Collections.<String>emptyList();
|
||||
|
||||
}
|
||||
options = getPlugin().getFlagsManager().getFlag(args.get(2).toUpperCase(Locale.ENGLISH)).map(f -> switch (f.getType()) {
|
||||
case PROTECTION -> getPlugin().getRanksManager()
|
||||
.getRanks().entrySet().stream()
|
||||
.filter(en -> en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK)
|
||||
.map(Entry::getKey)
|
||||
.map(user::getTranslation).collect(Collectors.toList());
|
||||
case SETTING -> Arrays.asList(active, disabled);
|
||||
default -> Collections.<String>emptyList();
|
||||
}).orElse(Collections.emptyList());
|
||||
}
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
|
@ -63,7 +63,7 @@ public class AdminSwitchtoCommand extends ConfirmableCommand {
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (NumberUtils.isDigits(args.get(1))) {
|
||||
try {
|
||||
Integer n = Integer.valueOf(args.get(1));
|
||||
int n = Integer.parseInt(args.get(1));
|
||||
if (n < 1 || n > islands.size()) {
|
||||
user.sendMessage("commands.admin.switchto.out-of-range", TextVariables.NUMBER, String.valueOf(islands.size()), TextVariables.LABEL, getTopLabel());
|
||||
return false;
|
||||
|
@ -87,6 +87,10 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
world = getPlugin().getIWM().getEndWorld(getWorld());
|
||||
}
|
||||
Location warpSpot = getSpot(world);
|
||||
if (world == null || warpSpot == null) {
|
||||
user.sendMessage("general.errors.no-safe-location-found");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, ask the admin to go to a safe spot
|
||||
String failureMessage = user.getTranslation("commands.admin.tp.manual", "[location]", warpSpot.getBlockX() + " " + warpSpot.getBlockY() + " "
|
||||
|
@ -7,6 +7,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
|
||||
public class AdminTrashCommand extends CompositeCommand {
|
||||
|
||||
@ -63,7 +64,7 @@ public class AdminTrashCommand extends CompositeCommand {
|
||||
user.sendMessage("commands.admin.trash.title");
|
||||
for (int i = 0; i < islands.size(); i++) {
|
||||
user.sendMessage("commands.admin.trash.count", TextVariables.NUMBER, String.valueOf(i+1));
|
||||
islands.get(i).showInfo(user);
|
||||
new IslandInfo(islands.get(i)).showInfo(user);
|
||||
}
|
||||
user.sendMessage("commands.admin.trash.use-switch", TextVariables.LABEL, getTopLabel());
|
||||
user.sendMessage("commands.admin.trash.use-emptytrash", TextVariables.LABEL, getTopLabel());
|
||||
|
@ -22,7 +22,7 @@ public class AdminVersionCommand extends CompositeCommand {
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
user.sendMessage("commands.bentobox.version.addon-syntax", TextVariables.NAME, getAddon().getDescription().getName(),
|
||||
TextVariables.VERSION, getAddon().getDescription().getVersion());
|
||||
TextVariables.VERSION, getAddon().getDescription().getVersion(), "[state]", getAddon().getState().name());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
new AdminTeamDisbandCommand(this);
|
||||
new AdminTeamSetownerCommand(this);
|
||||
new AdminTeamFixCommand(this);
|
||||
// Schems
|
||||
// Blueprints
|
||||
new AdminBlueprintCommand(this);
|
||||
// Register/unregister islands
|
||||
new AdminRegisterCommand(this);
|
||||
@ -96,7 +96,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
|
||||
/**
|
||||
* Defines what will be executed when this command is run.
|
||||
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List<String>)
|
||||
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List)
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
|
@ -70,7 +70,7 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
islands.clear();
|
||||
this.user = user;
|
||||
try {
|
||||
Integer days = Integer.parseInt(args.get(0));
|
||||
int days = Integer.parseInt(args.get(0));
|
||||
if (days < 1) {
|
||||
user.sendMessage("commands.admin.purge.days-one-or-more");
|
||||
return false;
|
||||
|
@ -24,7 +24,7 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
||||
private static final String HIDE = "hide";
|
||||
|
||||
// Map of users to which ranges must be displayed
|
||||
private Map<User, Integer> displayRanges = new HashMap<>();
|
||||
private final Map<User, Integer> displayRanges = new HashMap<>();
|
||||
|
||||
public AdminRangeDisplayCommand(CompositeCommand parent) {
|
||||
super(parent, DISPLAY, SHOW, HIDE);
|
||||
@ -46,29 +46,15 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
||||
|
||||
if (!displayRanges.containsKey(user)) {
|
||||
switch (label) {
|
||||
case DISPLAY:
|
||||
case SHOW:
|
||||
showZones(user);
|
||||
break;
|
||||
case HIDE:
|
||||
user.sendMessage("commands.admin.range.display.already-off");
|
||||
break;
|
||||
default:
|
||||
showHelp(this, user);
|
||||
break;
|
||||
case DISPLAY, SHOW -> showZones(user);
|
||||
case HIDE -> user.sendMessage("commands.admin.range.display.already-off");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
} else {
|
||||
switch (label) {
|
||||
case DISPLAY:
|
||||
case HIDE:
|
||||
hideZones(user);
|
||||
break;
|
||||
case SHOW:
|
||||
user.sendMessage("commands.admin.range.display.already-on");
|
||||
break;
|
||||
default:
|
||||
showHelp(this, user);
|
||||
break;
|
||||
case DISPLAY, HIDE -> hideZones(user);
|
||||
case SHOW -> user.sendMessage("commands.admin.range.display.already-on");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminTeamAddCommand extends CompositeCommand {
|
||||
@ -49,7 +50,10 @@ public class AdminTeamAddCommand extends CompositeCommand {
|
||||
}
|
||||
if (getIslands().inTeam(getWorld(), ownerUUID) && !getIslands().getOwner(getWorld(), ownerUUID).equals(ownerUUID)) {
|
||||
user.sendMessage("commands.admin.team.add.name-not-owner", TextVariables.NAME, args.get(0));
|
||||
getIslands().getIsland(getWorld(), ownerUUID).showMembers(user);
|
||||
Island island = getIslands().getIsland(getWorld(), ownerUUID);
|
||||
if (island != null) {
|
||||
new IslandInfo(island).showMembers(user);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
|
@ -13,6 +13,7 @@ import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
@ -59,10 +60,12 @@ public class AdminTeamKickCommand extends CompositeCommand {
|
||||
@Override
|
||||
public boolean execute(User user, String label, @NonNull List<String> args) {
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
|
||||
if (island == null) {
|
||||
return false;
|
||||
}
|
||||
if (targetUUID.equals(island.getOwner())) {
|
||||
user.sendMessage("commands.admin.team.kick.cannot-kick-owner");
|
||||
island.showMembers(user);
|
||||
new IslandInfo(island).showMembers(user);
|
||||
return false;
|
||||
}
|
||||
User target = User.getInstance(targetUUID);
|
||||
|
@ -32,6 +32,12 @@ public class IslandGoCommand extends DelayedTeleportCommand {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Check if mid-teleport
|
||||
if (getIslands().isGoingHome(user)) {
|
||||
// Tell them again that it's in progress
|
||||
user.sendMessage("commands.island.go.teleport");
|
||||
return false;
|
||||
}
|
||||
// Check if the island is reserved
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
|
@ -9,6 +9,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
@ -37,7 +38,7 @@ public class IslandInfoCommand extends CompositeCommand {
|
||||
}
|
||||
// If there are no args, then the player wants info on the island at this location
|
||||
if (args.isEmpty()) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.showInfo(user)).orElse(false)) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> new IslandInfo(i).showInfo(user)).orElse(false)) {
|
||||
user.sendMessage("commands.admin.info.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -56,10 +57,10 @@ public class IslandInfoCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Show info for this player
|
||||
island.showInfo(user);
|
||||
new IslandInfo(island).showInfo(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
|
@ -75,10 +75,9 @@ public class Invite {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof Invite)) {
|
||||
if (!(obj instanceof Invite other)) {
|
||||
return false;
|
||||
}
|
||||
Invite other = (Invite) obj;
|
||||
return Objects.equals(invitee, other.invitee) && Objects.equals(inviter, other.inviter) && type == other.type;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
* Invited list. Key is the invited party, value is the invite.
|
||||
* @since 1.8.0
|
||||
*/
|
||||
private Map<UUID, Invite> inviteMap;
|
||||
private final Map<UUID, Invite> inviteMap;
|
||||
|
||||
public IslandTeamCommand(CompositeCommand parent) {
|
||||
super(parent, "team");
|
||||
|
@ -22,7 +22,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
|
||||
private IslandTeamCommand itc;
|
||||
private final IslandTeamCommand itc;
|
||||
private @Nullable UUID targetUUID;
|
||||
|
||||
public IslandTeamCoopCommand(IslandTeamCommand parentCommand) {
|
||||
|
@ -20,7 +20,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
|
||||
private IslandTeamCommand itc;
|
||||
private final IslandTeamCommand itc;
|
||||
private UUID playerUUID;
|
||||
private UUID prospectiveOwnerUUID;
|
||||
|
||||
@ -50,16 +50,17 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
|
||||
return false;
|
||||
}
|
||||
// Check rank to of inviter
|
||||
Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
|
||||
String inviteUsage = getParent().getSubCommand("invite").map(CompositeCommand::getUsage).orElse("");
|
||||
if (island == null || island.getRank(prospectiveOwnerUUID) < island.getRankCommand(inviteUsage)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
|
||||
itc.removeInvite(playerUUID);
|
||||
return false;
|
||||
}
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
if (invite.getType().equals(Type.TEAM)) {
|
||||
// Check rank to of inviter
|
||||
Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
|
||||
String inviteUsage = getParent().getSubCommand("invite").map(CompositeCommand::getUsage).orElse("");
|
||||
if (island == null || island.getRank(prospectiveOwnerUUID) < island.getRankCommand(inviteUsage)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
|
||||
itc.removeInvite(playerUUID);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if player is already in a team
|
||||
if (getIslands().inTeam(getWorld(), playerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.you-already-are-in-team");
|
||||
@ -82,14 +83,10 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
// Get the invite
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
switch (invite.getType()) {
|
||||
case COOP:
|
||||
askConfirmation(user, () -> acceptCoopInvite(user, invite));
|
||||
break;
|
||||
case TRUST:
|
||||
askConfirmation(user, () -> acceptTrustInvite(user, invite));
|
||||
break;
|
||||
default:
|
||||
askConfirmation(user, user.getTranslation("commands.island.team.invite.accept.confirmation"), () -> acceptTeamInvite(user, invite));
|
||||
case COOP -> askConfirmation(user, () -> acceptCoopInvite(user, invite));
|
||||
case TRUST -> askConfirmation(user, () -> acceptTrustInvite(user, invite));
|
||||
default -> askConfirmation(user, user.getTranslation("commands.island.team.invite.accept.confirmation"),
|
||||
() -> acceptTeamInvite(user, invite));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
|
||||
private IslandTeamCommand itc;
|
||||
private final IslandTeamCommand itc;
|
||||
private @Nullable User invitedPlayer;
|
||||
|
||||
public IslandTeamInviteCommand(IslandTeamCommand parent) {
|
||||
@ -51,15 +51,9 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
String name = getPlayers().getName(playerUUID);
|
||||
switch (invite.getType()) {
|
||||
case COOP:
|
||||
user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name);
|
||||
break;
|
||||
case TRUST:
|
||||
user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name);
|
||||
break;
|
||||
default:
|
||||
user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name);
|
||||
break;
|
||||
case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name);
|
||||
case TRUST -> user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name);
|
||||
default -> user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import world.bentobox.bentobox.api.user.User;
|
||||
|
||||
public class IslandTeamInviteRejectCommand extends CompositeCommand {
|
||||
|
||||
private IslandTeamCommand itc;
|
||||
private final IslandTeamCommand itc;
|
||||
|
||||
public IslandTeamInviteRejectCommand(IslandTeamCommand islandTeamCommand) {
|
||||
super(islandTeamCommand, "reject");
|
||||
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* API for BentoBox commands
|
||||
*/
|
||||
/**
|
||||
* <p>
|
||||
* The workhorse class is the abstract class CompositeCommand. It provides all the functionality for
|
||||
* a command including automatic help, sub-commands, convenience methods, etc. See examples of how to use
|
||||
* it in the sub-folders admin and island.
|
||||
* </p>
|
||||
* <p>
|
||||
* The package also includes abstract confirmable command and delayed teleport command classes. These can
|
||||
* be extended for commands that need them. There is also a default help command. Commands can implement
|
||||
* their own custom help if required, but most of the time it is not.
|
||||
* </p>
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.commands;
|
@ -22,8 +22,8 @@ import world.bentobox.bentobox.database.yaml.YamlDatabase;
|
||||
*/
|
||||
public class Config<T> {
|
||||
|
||||
private AbstractDatabaseHandler<T> handler;
|
||||
private Logger logger;
|
||||
private final AbstractDatabaseHandler<T> handler;
|
||||
private final Logger logger;
|
||||
private Addon addon;
|
||||
|
||||
public Config(BentoBox plugin, Class<T> type) {
|
||||
|
@ -100,29 +100,21 @@ public class AddonEvent {
|
||||
}
|
||||
|
||||
private AddonBaseEvent getDeprecatedEvent() {
|
||||
switch (reason) {
|
||||
case ENABLE:
|
||||
return new AddonEnableEvent(addon, keyValues);
|
||||
case DISABLE:
|
||||
return new AddonDisableEvent(addon, keyValues);
|
||||
case LOAD:
|
||||
return new AddonLoadEvent(addon, keyValues);
|
||||
default:
|
||||
return new AddonGeneralEvent(addon, keyValues);
|
||||
}
|
||||
return switch (reason) {
|
||||
case ENABLE -> new AddonEnableEvent(addon, keyValues);
|
||||
case DISABLE -> new AddonDisableEvent(addon, keyValues);
|
||||
case LOAD -> new AddonLoadEvent(addon, keyValues);
|
||||
default -> new AddonGeneralEvent(addon, keyValues);
|
||||
};
|
||||
}
|
||||
|
||||
private AddonBaseEvent getEvent() {
|
||||
switch (reason) {
|
||||
case ENABLE:
|
||||
return new world.bentobox.bentobox.api.events.addon.AddonEnableEvent(addon, keyValues);
|
||||
case DISABLE:
|
||||
return new world.bentobox.bentobox.api.events.addon.AddonDisableEvent(addon, keyValues);
|
||||
case LOAD:
|
||||
return new world.bentobox.bentobox.api.events.addon.AddonLoadEvent(addon, keyValues);
|
||||
default:
|
||||
return new world.bentobox.bentobox.api.events.addon.AddonGeneralEvent(addon, keyValues);
|
||||
}
|
||||
return switch (reason) {
|
||||
case ENABLE -> new world.bentobox.bentobox.api.events.addon.AddonEnableEvent(addon, keyValues);
|
||||
case DISABLE -> new world.bentobox.bentobox.api.events.addon.AddonDisableEvent(addon, keyValues);
|
||||
case LOAD -> new world.bentobox.bentobox.api.events.addon.AddonLoadEvent(addon, keyValues);
|
||||
default -> new world.bentobox.bentobox.api.events.addon.AddonGeneralEvent(addon, keyValues);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -801,103 +801,58 @@ public class IslandEvent extends IslandBaseEvent {
|
||||
* @return deprecated event
|
||||
*/
|
||||
private IslandBaseEvent getDeprecatedEvent() {
|
||||
switch (reason) {
|
||||
case EXPEL:
|
||||
return new IslandExpelEvent(island, player, admin, location);
|
||||
case BAN:
|
||||
return new IslandBanEvent(island, player, admin, location);
|
||||
case PRECREATE:
|
||||
return new IslandPreCreateEvent(player);
|
||||
case CREATE:
|
||||
return new IslandCreateEvent(island, player, admin, location, blueprintBundle);
|
||||
case CREATED:
|
||||
return new IslandCreatedEvent(island, player, admin, location);
|
||||
case DELETE:
|
||||
return new IslandDeleteEvent(island, player, admin, location);
|
||||
case DELETE_CHUNKS:
|
||||
return new IslandDeleteChunksEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case DELETED:
|
||||
return new IslandDeletedEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case ENTER:
|
||||
return new IslandEnterEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case EXIT:
|
||||
return new IslandExitEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case LOCK:
|
||||
return new IslandLockEvent(island, player, admin, location);
|
||||
case RESET:
|
||||
return new IslandResetEvent(island, player, admin, location, blueprintBundle, oldIsland);
|
||||
case RESETTED:
|
||||
return new IslandResettedEvent(island, player, admin, location, oldIsland);
|
||||
case UNBAN:
|
||||
return new IslandUnbanEvent(island, player, admin, location);
|
||||
case UNLOCK:
|
||||
return new IslandUnlockEvent(island, player, admin, location);
|
||||
case REGISTERED:
|
||||
return new IslandRegisteredEvent(island, player, admin, location);
|
||||
case UNREGISTERED:
|
||||
return new IslandUnregisteredEvent(island, player, admin, location);
|
||||
case RANGE_CHANGE:
|
||||
return new IslandProtectionRangeChangeEvent(island, player, admin, location, newRange, oldRange);
|
||||
case PRECLEAR:
|
||||
return new IslandPreclearEvent(island, player, admin, location, oldIsland);
|
||||
case RESERVED:
|
||||
return new IslandReservedEvent(island, player, admin, location);
|
||||
case RANK_CHANGE:
|
||||
return new IslandRankChangeEvent(island, player, admin, location, oldRank, newRank);
|
||||
default:
|
||||
return new IslandGeneralEvent(island, player, admin, location);
|
||||
}
|
||||
return switch (reason) {
|
||||
case EXPEL -> new IslandExpelEvent(island, player, admin, location);
|
||||
case BAN -> new IslandBanEvent(island, player, admin, location);
|
||||
case PRECREATE -> new IslandPreCreateEvent(player);
|
||||
case CREATE -> new IslandCreateEvent(island, player, admin, location, blueprintBundle);
|
||||
case CREATED -> new IslandCreatedEvent(island, player, admin, location);
|
||||
case DELETE -> new IslandDeleteEvent(island, player, admin, location);
|
||||
case DELETE_CHUNKS -> new IslandDeleteChunksEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case DELETED -> new IslandDeletedEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case ENTER -> new IslandEnterEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case EXIT -> new IslandExitEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case LOCK -> new IslandLockEvent(island, player, admin, location);
|
||||
case RESET -> new IslandResetEvent(island, player, admin, location, blueprintBundle, oldIsland);
|
||||
case RESETTED -> new IslandResettedEvent(island, player, admin, location, oldIsland);
|
||||
case UNBAN -> new IslandUnbanEvent(island, player, admin, location);
|
||||
case UNLOCK -> new IslandUnlockEvent(island, player, admin, location);
|
||||
case REGISTERED -> new IslandRegisteredEvent(island, player, admin, location);
|
||||
case UNREGISTERED -> new IslandUnregisteredEvent(island, player, admin, location);
|
||||
case RANGE_CHANGE -> new IslandProtectionRangeChangeEvent(island, player, admin, location, newRange, oldRange);
|
||||
case PRECLEAR -> new IslandPreclearEvent(island, player, admin, location, oldIsland);
|
||||
case RESERVED -> new IslandReservedEvent(island, player, admin, location);
|
||||
case RANK_CHANGE -> new IslandRankChangeEvent(island, player, admin, location, oldRank, newRank);
|
||||
default -> new IslandGeneralEvent(island, player, admin, location);
|
||||
};
|
||||
}
|
||||
|
||||
private IslandBaseEvent getEvent() {
|
||||
switch (reason) {
|
||||
case EXPEL:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandExpelEvent(island, player, admin, location);
|
||||
case BAN:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandBanEvent(island, player, admin, location);
|
||||
case PRECREATE:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandPreCreateEvent(player);
|
||||
case CREATE:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandCreateEvent(island, player, admin, location, blueprintBundle);
|
||||
case CREATED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandCreatedEvent(island, player, admin, location);
|
||||
case DELETE:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandDeleteEvent(island, player, admin, location);
|
||||
case DELETE_CHUNKS:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandDeleteChunksEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case DELETED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandDeletedEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case ENTER:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandEnterEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case EXIT:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandExitEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case LOCK:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandLockEvent(island, player, admin, location);
|
||||
case RESET:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandResetEvent(island, player, admin, location, blueprintBundle, oldIsland);
|
||||
case RESETTED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandResettedEvent(island, player, admin, location, oldIsland);
|
||||
case UNBAN:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandUnbanEvent(island, player, admin, location);
|
||||
case UNLOCK:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandUnlockEvent(island, player, admin, location);
|
||||
case REGISTERED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandRegisteredEvent(island, player, admin, location);
|
||||
case UNREGISTERED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandUnregisteredEvent(island, player, admin, location);
|
||||
case RANGE_CHANGE:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent(island, player, admin, location, newRange, oldRange);
|
||||
case PRECLEAR:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandPreclearEvent(island, player, admin, location, oldIsland);
|
||||
case RESERVED:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandReservedEvent(island, player, admin, location);
|
||||
case RANK_CHANGE:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandRankChangeEvent(island, player, admin, location, oldRank, newRank);
|
||||
case NEW_ISLAND:
|
||||
return new IslandNewIslandEvent(island, player, admin, location);
|
||||
default:
|
||||
return new world.bentobox.bentobox.api.events.island.IslandGeneralEvent(island, player, admin, location);
|
||||
}
|
||||
return switch (reason) {
|
||||
case EXPEL -> new world.bentobox.bentobox.api.events.island.IslandExpelEvent(island, player, admin, location);
|
||||
case BAN -> new world.bentobox.bentobox.api.events.island.IslandBanEvent(island, player, admin, location);
|
||||
case PRECREATE -> new world.bentobox.bentobox.api.events.island.IslandPreCreateEvent(player);
|
||||
case CREATE -> new world.bentobox.bentobox.api.events.island.IslandCreateEvent(island, player, admin, location, blueprintBundle);
|
||||
case CREATED -> new world.bentobox.bentobox.api.events.island.IslandCreatedEvent(island, player, admin, location);
|
||||
case DELETE -> new world.bentobox.bentobox.api.events.island.IslandDeleteEvent(island, player, admin, location);
|
||||
case DELETE_CHUNKS -> new world.bentobox.bentobox.api.events.island.IslandDeleteChunksEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case DELETED -> new world.bentobox.bentobox.api.events.island.IslandDeletedEvent(island, player, admin, location, deletedIslandInfo);
|
||||
case ENTER -> new world.bentobox.bentobox.api.events.island.IslandEnterEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case EXIT -> new world.bentobox.bentobox.api.events.island.IslandExitEvent(island, player, admin, location, oldIsland, rawEvent);
|
||||
case LOCK -> new world.bentobox.bentobox.api.events.island.IslandLockEvent(island, player, admin, location);
|
||||
case RESET -> new world.bentobox.bentobox.api.events.island.IslandResetEvent(island, player, admin, location, blueprintBundle, oldIsland);
|
||||
case RESETTED -> new world.bentobox.bentobox.api.events.island.IslandResettedEvent(island, player, admin, location, oldIsland);
|
||||
case UNBAN -> new world.bentobox.bentobox.api.events.island.IslandUnbanEvent(island, player, admin, location);
|
||||
case UNLOCK -> new world.bentobox.bentobox.api.events.island.IslandUnlockEvent(island, player, admin, location);
|
||||
case REGISTERED -> new world.bentobox.bentobox.api.events.island.IslandRegisteredEvent(island, player, admin, location);
|
||||
case UNREGISTERED -> new world.bentobox.bentobox.api.events.island.IslandUnregisteredEvent(island, player, admin, location);
|
||||
case RANGE_CHANGE -> new world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent(island, player, admin, location, newRange, oldRange);
|
||||
case PRECLEAR -> new world.bentobox.bentobox.api.events.island.IslandPreclearEvent(island, player, admin, location, oldIsland);
|
||||
case RESERVED -> new world.bentobox.bentobox.api.events.island.IslandReservedEvent(island, player, admin, location);
|
||||
case RANK_CHANGE -> new world.bentobox.bentobox.api.events.island.IslandRankChangeEvent(island, player, admin, location, oldRank, newRank);
|
||||
case NEW_ISLAND -> new IslandNewIslandEvent(island, player, admin, location);
|
||||
default -> new world.bentobox.bentobox.api.events.island.IslandGeneralEvent(island, player, admin, location);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* API for all the events that BentoBox generates
|
||||
*/
|
||||
/**
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.events;
|
@ -237,57 +237,35 @@ public class TeamEvent {
|
||||
}
|
||||
|
||||
private IslandBaseEvent getDeprecatedEvent() {
|
||||
switch (reason) {
|
||||
case JOIN:
|
||||
return new TeamJoinEvent(island, player, admin, location);
|
||||
case JOINED:
|
||||
return new TeamJoinedEvent(island, player, admin, location);
|
||||
case INVITE:
|
||||
return new TeamInviteEvent(island, player, admin, location);
|
||||
case LEAVE:
|
||||
return new TeamLeaveEvent(island, player, admin, location);
|
||||
case REJECT:
|
||||
return new TeamRejectEvent(island, player, admin, location);
|
||||
case KICK:
|
||||
return new TeamKickEvent(island, player, admin, location);
|
||||
case SETOWNER:
|
||||
return new TeamSetownerEvent(island, player, admin, location);
|
||||
case INFO:
|
||||
return new TeamInfoEvent(island, player, admin, location);
|
||||
case DELETE:
|
||||
return new TeamDeleteEvent(island, player, admin, location);
|
||||
case UNINVITE:
|
||||
return new TeamUninviteEvent(island, player, admin, location);
|
||||
default:
|
||||
return new TeamGeneralEvent(island, player, admin, location);
|
||||
}
|
||||
return switch (reason) {
|
||||
case JOIN -> new TeamJoinEvent(island, player, admin, location);
|
||||
case JOINED -> new TeamJoinedEvent(island, player, admin, location);
|
||||
case INVITE -> new TeamInviteEvent(island, player, admin, location);
|
||||
case LEAVE -> new TeamLeaveEvent(island, player, admin, location);
|
||||
case REJECT -> new TeamRejectEvent(island, player, admin, location);
|
||||
case KICK -> new TeamKickEvent(island, player, admin, location);
|
||||
case SETOWNER -> new TeamSetownerEvent(island, player, admin, location);
|
||||
case INFO -> new TeamInfoEvent(island, player, admin, location);
|
||||
case DELETE -> new TeamDeleteEvent(island, player, admin, location);
|
||||
case UNINVITE -> new TeamUninviteEvent(island, player, admin, location);
|
||||
default -> new TeamGeneralEvent(island, player, admin, location);
|
||||
};
|
||||
}
|
||||
|
||||
private IslandBaseEvent getEvent() {
|
||||
switch (reason) {
|
||||
case JOIN:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamJoinEvent(island, player, admin, location);
|
||||
case JOINED:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamJoinedEvent(island, player, admin, location);
|
||||
case INVITE:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamInviteEvent(island, player, admin, location);
|
||||
case LEAVE:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamLeaveEvent(island, player, admin, location);
|
||||
case REJECT:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamRejectEvent(island, player, admin, location);
|
||||
case KICK:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamKickEvent(island, player, admin, location);
|
||||
case SETOWNER:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamSetownerEvent(island, player, admin, location);
|
||||
case INFO:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamInfoEvent(island, player, admin, location);
|
||||
case DELETE:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamDeleteEvent(island, player, admin, location);
|
||||
case UNINVITE:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamUninviteEvent(island, player, admin, location);
|
||||
default:
|
||||
return new world.bentobox.bentobox.api.events.team.TeamGeneralEvent(island, player, admin, location);
|
||||
}
|
||||
return switch (reason) {
|
||||
case JOIN -> new world.bentobox.bentobox.api.events.team.TeamJoinEvent(island, player, admin, location);
|
||||
case JOINED -> new world.bentobox.bentobox.api.events.team.TeamJoinedEvent(island, player, admin, location);
|
||||
case INVITE -> new world.bentobox.bentobox.api.events.team.TeamInviteEvent(island, player, admin, location);
|
||||
case LEAVE -> new world.bentobox.bentobox.api.events.team.TeamLeaveEvent(island, player, admin, location);
|
||||
case REJECT -> new world.bentobox.bentobox.api.events.team.TeamRejectEvent(island, player, admin, location);
|
||||
case KICK -> new world.bentobox.bentobox.api.events.team.TeamKickEvent(island, player, admin, location);
|
||||
case SETOWNER -> new world.bentobox.bentobox.api.events.team.TeamSetownerEvent(island, player, admin, location);
|
||||
case INFO -> new world.bentobox.bentobox.api.events.team.TeamInfoEvent(island, player, admin, location);
|
||||
case DELETE -> new world.bentobox.bentobox.api.events.team.TeamDeleteEvent(island, player, admin, location);
|
||||
case UNINVITE -> new world.bentobox.bentobox.api.events.team.TeamUninviteEvent(island, player, admin, location);
|
||||
default -> new world.bentobox.bentobox.api.events.team.TeamGeneralEvent(island, player, admin, location);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,8 @@ import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.ItemParser;
|
||||
|
||||
|
||||
public class Flag implements Comparable<Flag> {
|
||||
|
||||
@ -51,7 +53,8 @@ public class Flag implements Comparable<Flag> {
|
||||
*/
|
||||
WORLD_SETTING(Material.GRASS_BLOCK);
|
||||
|
||||
private @NonNull Material icon;
|
||||
private @NonNull
|
||||
final Material icon;
|
||||
|
||||
Type(@NonNull Material icon) {
|
||||
this.icon = icon;
|
||||
@ -91,14 +94,11 @@ public class Flag implements Comparable<Flag> {
|
||||
* @return next ranking mode
|
||||
*/
|
||||
public Mode getNext() {
|
||||
switch(this) {
|
||||
case ADVANCED:
|
||||
return EXPERT;
|
||||
case BASIC:
|
||||
return ADVANCED;
|
||||
default:
|
||||
return BASIC;
|
||||
}
|
||||
return switch (this) {
|
||||
case ADVANCED -> EXPERT;
|
||||
case BASIC -> ADVANCED;
|
||||
default -> BASIC;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,14 +107,11 @@ public class Flag implements Comparable<Flag> {
|
||||
* @return true if ranked greater
|
||||
*/
|
||||
public boolean isGreaterThan(Mode rank) {
|
||||
switch(this) {
|
||||
case EXPERT:
|
||||
return rank.equals(BASIC) || rank.equals(ADVANCED);
|
||||
case ADVANCED:
|
||||
return rank.equals(BASIC);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return switch (this) {
|
||||
case EXPERT -> rank.equals(BASIC) || rank.equals(ADVANCED);
|
||||
case ADVANCED -> rank.equals(BASIC);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,12 +204,12 @@ public class Flag implements Comparable<Flag> {
|
||||
// Subflag support
|
||||
if (hasSubflags()) {
|
||||
subflags.stream()
|
||||
.filter(subflag -> subflag.getType().equals(Type.WORLD_SETTING) || subflag.getType().equals(Type.PROTECTION))
|
||||
.forEach(subflag -> BentoBox.getInstance()
|
||||
.getIWM()
|
||||
.getWorldSettings(world)
|
||||
.getWorldFlags()
|
||||
.put(subflag.getID(), setting));
|
||||
.filter(subflag -> subflag.getType().equals(Type.WORLD_SETTING) || subflag.getType().equals(Type.PROTECTION))
|
||||
.forEach(subflag -> BentoBox.getInstance()
|
||||
.getIWM()
|
||||
.getWorldSettings(world)
|
||||
.getWorldFlags()
|
||||
.put(subflag.getID(), setting));
|
||||
}
|
||||
|
||||
// Save config file
|
||||
@ -222,7 +219,7 @@ public class Flag implements Comparable<Flag> {
|
||||
|
||||
/**
|
||||
* Set the original status of this flag for locations outside of island spaces.
|
||||
* May be overriden by the the setting for this world.
|
||||
* May be overridden by the setting for this world.
|
||||
* Does not affect subflags.
|
||||
* @param defaultSetting - true means it is allowed. false means it is not allowed
|
||||
*/
|
||||
@ -300,10 +297,9 @@ public class Flag implements Comparable<Flag> {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof Flag)) {
|
||||
if (!(obj instanceof Flag other)) {
|
||||
return false;
|
||||
}
|
||||
Flag other = (Flag) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
@ -322,6 +318,13 @@ public class Flag implements Comparable<Flag> {
|
||||
return PROTECTION_FLAGS + this.id + ".name";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a locale reference for the icon of this protection flag
|
||||
*/
|
||||
public String getIconReference() {
|
||||
return PROTECTION_FLAGS + this.id + ".icon";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a locale reference for the description of this protection flag
|
||||
*/
|
||||
@ -384,7 +387,7 @@ public class Flag implements Comparable<Flag> {
|
||||
}
|
||||
// Start the flag conversion
|
||||
PanelItemBuilder pib = new PanelItemBuilder()
|
||||
.icon(new ItemStack(icon))
|
||||
.icon(ItemParser.parse(user.getTranslationOrNothing(this.getIconReference()), new ItemStack(icon)))
|
||||
.name(user.getTranslation("protection.panel.flag-item.name-layout", TextVariables.NAME, user.getTranslation(getNameReference())))
|
||||
.clickHandler(clickHandler)
|
||||
.invisible(invisible);
|
||||
@ -392,16 +395,11 @@ public class Flag implements Comparable<Flag> {
|
||||
pib.description(user.getTranslation("protection.panel.flag-item.menu-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference())));
|
||||
return pib.build();
|
||||
}
|
||||
switch(getType()) {
|
||||
case PROTECTION:
|
||||
return createProtectionFlag(plugin, user, island, pib).build();
|
||||
case SETTING:
|
||||
return createSettingFlag(user, island, pib).build();
|
||||
case WORLD_SETTING:
|
||||
return createWorldSettingFlag(user, pib).build();
|
||||
default:
|
||||
return pib.build();
|
||||
}
|
||||
return switch (getType()) {
|
||||
case PROTECTION -> createProtectionFlag(plugin, user, island, pib).build();
|
||||
case SETTING -> createSettingFlag(user, island, pib).build();
|
||||
case WORLD_SETTING -> createWorldSettingFlag(user, pib).build();
|
||||
};
|
||||
}
|
||||
|
||||
private PanelItemBuilder createWorldSettingFlag(User user, PanelItemBuilder pib) {
|
||||
@ -484,8 +482,8 @@ public class Flag implements Comparable<Flag> {
|
||||
*/
|
||||
public static class Builder {
|
||||
// Mandatory fields
|
||||
private String id;
|
||||
private Material icon;
|
||||
private final String id;
|
||||
private final Material icon;
|
||||
|
||||
// Listener
|
||||
private Listener listener;
|
||||
@ -514,7 +512,7 @@ public class Flag implements Comparable<Flag> {
|
||||
private Mode mode = Mode.EXPERT;
|
||||
|
||||
// Subflags
|
||||
private Set<Flag> subflags;
|
||||
private final Set<Flag> subflags;
|
||||
|
||||
/**
|
||||
* Builder for making flags
|
||||
@ -638,7 +636,7 @@ public class Flag implements Comparable<Flag> {
|
||||
* Take extra care to ensure that subflags have the same number of possible values as the parent flag.
|
||||
* @param flags all Flags that are subflags
|
||||
* @return Builder - flag builder
|
||||
* @since 1.17.0
|
||||
* @since 1.17.1
|
||||
*/
|
||||
public Builder subflags(Flag... flags) {
|
||||
this.subflags.addAll(Arrays.asList(flags));
|
||||
@ -653,17 +651,9 @@ public class Flag implements Comparable<Flag> {
|
||||
// If no clickHandler has been set, then apply default ones
|
||||
if (clickHandler == null) {
|
||||
switch (type) {
|
||||
case SETTING:
|
||||
clickHandler = new IslandToggleClick(id);
|
||||
break;
|
||||
case WORLD_SETTING:
|
||||
clickHandler = new WorldToggleClick(id);
|
||||
break;
|
||||
case PROTECTION:
|
||||
// Default option
|
||||
default:
|
||||
clickHandler = new CycleClick(id);
|
||||
break;
|
||||
case SETTING -> clickHandler = new IslandToggleClick(id);
|
||||
case WORLD_SETTING -> clickHandler = new WorldToggleClick(id);
|
||||
default -> clickHandler = new CycleClick(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
@ -18,6 +19,7 @@ import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.metadata.MetaDataValue;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
@ -253,4 +255,22 @@ public abstract class FlagListener implements Listener {
|
||||
protected IslandWorldManager getIWM() {
|
||||
return plugin.getIWM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if PVP is allowed here or not
|
||||
* @param location location where action is taking
|
||||
* @return true if PVP is allowed, false if not
|
||||
*/
|
||||
protected boolean PVPAllowed(Location location) {
|
||||
return plugin.getIslands().getIslandAt(location).map(i -> i.isAllowed(this.getFlag(location.getWorld()))).orElse(false);
|
||||
}
|
||||
|
||||
protected Flag getFlag(World w) {
|
||||
return switch (w.getEnvironment()) {
|
||||
case NETHER -> Flags.PVP_NETHER;
|
||||
case THE_END -> Flags.PVP_END;
|
||||
default -> Flags.PVP_OVERWORLD;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class IslandToggleClick implements ClickHandler {
|
||||
|
||||
private BentoBox plugin = BentoBox.getInstance();
|
||||
private String id;
|
||||
private final BentoBox plugin = BentoBox.getInstance();
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* @param id - the flag ID that this click listener is associated with
|
||||
|
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* This package contains click listener classes used when clicking on icons in settings
|
||||
*
|
||||
* <p>
|
||||
* CycleClick will cycle through different settings. IslandLock is specific to locking or unlocking an island.
|
||||
* IslandToggleClick is a toggle-based selection. WorldToggleClick toggles world settings.
|
||||
*/
|
||||
/**
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.flags.clicklisteners;
|
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* This package contains the API for protection and settings flags
|
||||
*
|
||||
* <p>
|
||||
* New flags should use the Flag.Builder to create a flag. Listeners for flag related events should
|
||||
* extend the abstract FlagListener class.
|
||||
* </p>
|
||||
* <p>
|
||||
* Click listeners are different types of listeners specific to clicking on the settings UI in which the
|
||||
* flags are shown.
|
||||
* </p>
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.flags;
|
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Provides API to enable BentoBox to hook into other plugins.
|
||||
*
|
||||
* <p>
|
||||
* This is used to hook into plugins like Placeholder API
|
||||
* </p>
|
||||
*/
|
||||
/**
|
||||
* @author Poslovich
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.hooks;
|
@ -20,16 +20,16 @@ public class BentoBoxLocale {
|
||||
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
private Locale locale;
|
||||
private YamlConfiguration config;
|
||||
private ItemStack banner;
|
||||
private List<String> authors;
|
||||
private final Locale locale;
|
||||
private final YamlConfiguration config;
|
||||
private final ItemStack banner;
|
||||
private final List<String> authors;
|
||||
|
||||
/**
|
||||
* List of available prefixes in this locale.
|
||||
* @since 1.12.0
|
||||
*/
|
||||
private Set<String> prefixes;
|
||||
private final Set<String> prefixes;
|
||||
|
||||
public BentoBoxLocale(Locale locale, YamlConfiguration config) {
|
||||
this.locale = locale;
|
||||
|
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* API for localization.
|
||||
*
|
||||
* <p>
|
||||
* BentoBoxLocale holds all the information required to specify a locale in BentoBox.
|
||||
* TextVariables contains a static constants that are used as place holders in user messaging.
|
||||
* </p>
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.localization;
|
@ -47,7 +47,7 @@ public class LogEntry {
|
||||
|
||||
public static class Builder {
|
||||
private long timestamp;
|
||||
private String type;
|
||||
private final String type;
|
||||
private Map<String, String> data;
|
||||
|
||||
public Builder(@NonNull String type) {
|
||||
|
@ -13,13 +13,13 @@ public interface MetaDataAble {
|
||||
/**
|
||||
* @return the metaData
|
||||
*/
|
||||
public Optional<Map<String, MetaDataValue>> getMetaData();
|
||||
Optional<Map<String, MetaDataValue>> getMetaData();
|
||||
|
||||
/**
|
||||
* @param metaData the metaData to set
|
||||
* @since 1.15.4
|
||||
*/
|
||||
public void setMetaData(Map<String, MetaDataValue> metaData);
|
||||
void setMetaData(Map<String, MetaDataValue> metaData);
|
||||
|
||||
/**
|
||||
* Get meta data by key
|
||||
|
@ -29,7 +29,7 @@ public class MetaDataValue {
|
||||
@Expose
|
||||
private Boolean booleanValue;
|
||||
@Expose
|
||||
private @NonNull String stringValue;
|
||||
private String stringValue;
|
||||
|
||||
/**
|
||||
* Initialize this meta data value
|
||||
@ -85,6 +85,6 @@ public class MetaDataValue {
|
||||
|
||||
@NonNull
|
||||
public String asString() {
|
||||
return stringValue;
|
||||
return stringValue == null ? "" : stringValue;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Metadata API for storing data in BentoBox database objects
|
||||
* <p>
|
||||
* This API draws on the same concepts as Bukkit's meta data API.
|
||||
* Classes capable of storing meta data will implement the MetaDataAble interface.
|
||||
* MetaDataValue provides the actual object in which data is stored.
|
||||
/* </p>
|
||||
* @author tastybento
|
||||
* @since 1.15.4
|
||||
*/
|
||||
package world.bentobox.bentobox.api.metadata;
|
@ -80,15 +80,9 @@ public class Panel implements HeadRequester, InventoryHolder {
|
||||
|
||||
// Create panel
|
||||
switch (type) {
|
||||
case INVENTORY:
|
||||
inventory = Bukkit.createInventory(null, fixSize(size), name);
|
||||
break;
|
||||
case HOPPER:
|
||||
inventory = Bukkit.createInventory(null, InventoryType.HOPPER, name);
|
||||
break;
|
||||
case DROPPER:
|
||||
inventory = Bukkit.createInventory(null, InventoryType.DROPPER, name);
|
||||
break;
|
||||
case INVENTORY -> inventory = Bukkit.createInventory(null, fixSize(size), name);
|
||||
case HOPPER -> inventory = Bukkit.createInventory(null, InventoryType.HOPPER, name);
|
||||
case DROPPER -> inventory = Bukkit.createInventory(null, InventoryType.DROPPER, name);
|
||||
}
|
||||
|
||||
// Fill the inventory and return
|
||||
|
@ -29,7 +29,7 @@ public class PanelItem {
|
||||
private String name;
|
||||
private boolean glow;
|
||||
private ItemMeta meta;
|
||||
private String playerHeadName;
|
||||
private final String playerHeadName;
|
||||
private boolean invisible;
|
||||
|
||||
public PanelItem(PanelItemBuilder builtItem) {
|
||||
|
@ -31,7 +31,8 @@ public class TabbedPanel extends Panel implements PanelListener {
|
||||
private static final String PROTECTION_PANEL = "protection.panel.";
|
||||
private static final long ITEMS_PER_PAGE = 36;
|
||||
private final TabbedPanelBuilder tpb;
|
||||
private @NonNull BentoBox plugin = BentoBox.getInstance();
|
||||
private @NonNull
|
||||
final BentoBox plugin = BentoBox.getInstance();
|
||||
private int activeTab;
|
||||
private int activePage;
|
||||
private boolean closed;
|
||||
@ -146,7 +147,7 @@ public class TabbedPanel extends Panel implements PanelListener {
|
||||
}
|
||||
}
|
||||
// Add any subsidiary icons
|
||||
tab.getTabIcons().forEach(items::put);
|
||||
items.putAll(tab.getTabIcons());
|
||||
}
|
||||
|
||||
private void setupFooter(TreeMap<Integer, PanelItem> items) {
|
||||
|
@ -0,0 +1,527 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels;
|
||||
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
|
||||
|
||||
/**
|
||||
* This class creates a new Panel from the template record.
|
||||
* @author BONNe
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public class TemplatedPanel extends Panel
|
||||
{
|
||||
/**
|
||||
* TemplatedPanel constructor class which generates functional panel.
|
||||
* @param builder Builder that contains all information about the panel that must be generated.
|
||||
*/
|
||||
public TemplatedPanel(@NonNull TemplatedPanelBuilder builder)
|
||||
{
|
||||
this.user = builder.getUser();
|
||||
this.setWorld(builder.getWorld());
|
||||
this.setListener(builder.getListener());
|
||||
|
||||
this.panelTemplate = builder.getPanelTemplate();
|
||||
// Init type creators
|
||||
this.typeCreators = new HashMap<>(builder.getObjectCreatorMap());
|
||||
this.typeIndex = new HashMap<>(builder.getObjectCreatorMap().size());
|
||||
this.typeSlotMap = new HashMap<>(builder.getObjectCreatorMap().size());
|
||||
|
||||
if (this.panelTemplate == null)
|
||||
{
|
||||
BentoBox.getInstance().logError("Cannot generate panel because template is not loaded.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.generatePanel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method generates the panel from the template.
|
||||
*/
|
||||
private void generatePanel()
|
||||
{
|
||||
Map<Integer, PanelItem> items = switch (this.panelTemplate.type())
|
||||
{
|
||||
case INVENTORY -> this.populateInventoryPanel();
|
||||
case HOPPER -> this.populateHopperPanel();
|
||||
case DROPPER -> this.populateDropperPanel();
|
||||
};
|
||||
|
||||
super.makePanel(this.user.getTranslation(this.panelTemplate.title()),
|
||||
items,
|
||||
items.keySet().stream().max(Comparator.naturalOrder()).orElse(9),
|
||||
this.user,
|
||||
this.getListener().orElse(null),
|
||||
this.panelTemplate.type());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates map with item indexes and their icons that will be added into
|
||||
* Inventory Panel.
|
||||
* @return Map that contains indexes linked to the correct panel item.
|
||||
*/
|
||||
@NonNull
|
||||
private Map<Integer, PanelItem> populateInventoryPanel()
|
||||
{
|
||||
// Init item array with the max available size.
|
||||
PanelItem[][] itemArray = new PanelItem[6][9];
|
||||
|
||||
// Analyze the GUI button layout a bit.
|
||||
for (int i = 0; i < this.panelTemplate.content().length; i++)
|
||||
{
|
||||
for (int k = 0; k < this.panelTemplate.content()[i].length; k++)
|
||||
{
|
||||
ItemTemplateRecord record = this.panelTemplate.content()[i][k];
|
||||
|
||||
if (record != null && record.dataMap().containsKey("type"))
|
||||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make buttons for the GUI
|
||||
for (int i = 0; i < this.panelTemplate.content().length; i++)
|
||||
{
|
||||
for (int k = 0; k < this.panelTemplate.content()[i].length; k++)
|
||||
{
|
||||
itemArray[i][k] = this.makeButton(this.panelTemplate.content()[i][k]);
|
||||
}
|
||||
}
|
||||
|
||||
// After items are created, remove empty lines.
|
||||
boolean[] showLine = this.panelTemplate.forcedRows();
|
||||
|
||||
for (int i = 0; i < this.panelTemplate.content().length; i++)
|
||||
{
|
||||
boolean emptyLine = true;
|
||||
|
||||
for (int k = 0; emptyLine && k < this.panelTemplate.content()[i].length; k++)
|
||||
{
|
||||
emptyLine = itemArray[i][k] == null;
|
||||
}
|
||||
|
||||
// Do not generate fallback for "empty" lines.
|
||||
showLine[i] = showLine[i] || !emptyLine;
|
||||
}
|
||||
|
||||
// Now fill the border.
|
||||
if (this.panelTemplate.border() != null)
|
||||
{
|
||||
PanelItem template = this.makeTemplate(this.panelTemplate.border());
|
||||
|
||||
// Hard codded 6
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (i == 0 || i == 5)
|
||||
{
|
||||
// Fill first and last row completely with border.
|
||||
for (int k = 0; k < 9; k++)
|
||||
{
|
||||
if (itemArray[i][k] == null)
|
||||
{
|
||||
itemArray[i][k] = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fill first and last element in row with border.
|
||||
if (itemArray[i][0] == null)
|
||||
{
|
||||
itemArray[i][0] = template;
|
||||
}
|
||||
|
||||
if (itemArray[i][8] == null)
|
||||
{
|
||||
itemArray[i][8] = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showLine[0] = true;
|
||||
showLine[5] = true;
|
||||
}
|
||||
|
||||
// Now fill the background.
|
||||
if (this.panelTemplate.background() != null)
|
||||
{
|
||||
PanelItem template = this.makeTemplate(this.panelTemplate.background());
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
for (int k = 0; k < 9; k++)
|
||||
{
|
||||
if (itemArray[i][k] == null)
|
||||
{
|
||||
itemArray[i][k] = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now place all panel items with their indexes into item map.
|
||||
Map<Integer, PanelItem> itemMap = new HashMap<>(6 * 9);
|
||||
|
||||
int correctIndex = 0;
|
||||
|
||||
for (int i = 0; i < itemArray.length; i++)
|
||||
{
|
||||
final boolean iterate = showLine[i];
|
||||
|
||||
for (int k = 0; iterate && k < itemArray[i].length; k++)
|
||||
{
|
||||
if (itemArray[i][k] != null)
|
||||
{
|
||||
itemMap.put(correctIndex, itemArray[i][k]);
|
||||
}
|
||||
|
||||
correctIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates map with item indexes and their icons that will be added into
|
||||
* hopper Panel.
|
||||
* @return Map that contains indexes linked to the correct panel item.
|
||||
*/
|
||||
@NonNull
|
||||
private Map<Integer, PanelItem> populateHopperPanel()
|
||||
{
|
||||
// Init item array with the max available size.
|
||||
PanelItem[] itemArray = new PanelItem[5];
|
||||
|
||||
// Analyze the template
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
ItemTemplateRecord record = this.panelTemplate.content()[0][i];
|
||||
|
||||
if (record != null && record.dataMap().containsKey("type"))
|
||||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Make buttons
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
itemArray[i] = this.makeButton(this.panelTemplate.content()[0][i]);
|
||||
}
|
||||
|
||||
// Now fill the background.
|
||||
if (this.panelTemplate.background() != null)
|
||||
{
|
||||
PanelItem template = this.makeTemplate(this.panelTemplate.background());
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (itemArray[i] == null)
|
||||
{
|
||||
itemArray[i] = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now place all panel items with their indexes into item map.
|
||||
Map<Integer, PanelItem> itemMap = new HashMap<>(5);
|
||||
|
||||
int correctIndex = 0;
|
||||
|
||||
for (PanelItem panelItem : itemArray)
|
||||
{
|
||||
if (panelItem != null)
|
||||
{
|
||||
itemMap.put(correctIndex, panelItem);
|
||||
}
|
||||
|
||||
correctIndex++;
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates map with item indexes and their icons that will be added into
|
||||
* dropper Panel.
|
||||
* @return Map that contains indexes linked to the correct panel item.
|
||||
*/
|
||||
@NonNull
|
||||
private Map<Integer, PanelItem> populateDropperPanel()
|
||||
{
|
||||
// Analyze the template
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
ItemTemplateRecord record = this.panelTemplate.content()[i][k];
|
||||
|
||||
if (record != null && record.dataMap().containsKey("type"))
|
||||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init item array with the max available size.
|
||||
PanelItem[][] itemArray = new PanelItem[3][3];
|
||||
|
||||
// Make buttons
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
itemArray[i][k] = this.makeButton(this.panelTemplate.content()[i][k]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now fill the background.
|
||||
if (this.panelTemplate.background() != null)
|
||||
{
|
||||
PanelItem template = this.makeTemplate(this.panelTemplate.background());
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
if (itemArray[i][k] == null)
|
||||
{
|
||||
itemArray[i][k] = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init item map with the max available size.
|
||||
Map<Integer, PanelItem> itemMap = new HashMap<>(9);
|
||||
|
||||
int correctIndex = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
if (itemArray[i][k] != null)
|
||||
{
|
||||
itemMap.put(correctIndex, itemArray[i][k]);
|
||||
}
|
||||
|
||||
correctIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method passes button creation from given record template.
|
||||
* @param record Template of the button that must be created.
|
||||
* @return PanelItem of the template, otherwise null.
|
||||
*/
|
||||
@Nullable
|
||||
private PanelItem makeButton(@Nullable ItemTemplateRecord record)
|
||||
{
|
||||
if (record == null)
|
||||
{
|
||||
// Immediate exit if record is null.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (record.dataMap().containsKey("type"))
|
||||
{
|
||||
// If dataMap is not null, and it is not empty, then pass button to the object creator function.
|
||||
|
||||
return this.makeAddonButton(record);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanelItemBuilder itemBuilder = new PanelItemBuilder();
|
||||
|
||||
if (record.icon() != null)
|
||||
{
|
||||
itemBuilder.icon(record.icon().clone());
|
||||
}
|
||||
|
||||
if (record.title() != null)
|
||||
{
|
||||
itemBuilder.name(this.user.getTranslation(record.title()));
|
||||
}
|
||||
|
||||
if (record.description() != null)
|
||||
{
|
||||
itemBuilder.description(this.user.getTranslation(record.description()));
|
||||
}
|
||||
|
||||
// If there are generic click handlers that could be added, then this is a place
|
||||
// where to process them.
|
||||
|
||||
// Click Handlers are managed by custom addon buttons.
|
||||
return itemBuilder.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method passes button to the type creator, if that exists.
|
||||
* @param record Template of the button that must be created.
|
||||
* @return PanelItem of the button created by typeCreator, otherwise null.
|
||||
*/
|
||||
@Nullable
|
||||
private PanelItem makeAddonButton(@NonNull ItemTemplateRecord record)
|
||||
{
|
||||
// Get object type.
|
||||
String type = String.valueOf(record.dataMap().getOrDefault("type", ""));
|
||||
|
||||
if (!this.typeCreators.containsKey(type))
|
||||
{
|
||||
// There are no object with a given type.
|
||||
return this.makeFallBack(record.fallback());
|
||||
}
|
||||
|
||||
BiFunction<ItemTemplateRecord, ItemSlot, PanelItem> buttonBuilder = this.typeCreators.get(type);
|
||||
|
||||
// Get next slot index.
|
||||
ItemSlot itemSlot = this.typeIndex.containsKey(type) ?
|
||||
this.typeIndex.get(type) :
|
||||
new ItemSlot(0, this.typeSlotMap);
|
||||
this.typeIndex.put(type, itemSlot.nextItemSlot());
|
||||
|
||||
// Try to get next object.
|
||||
PanelItem item = buttonBuilder.apply(record, itemSlot);
|
||||
return item == null ? this.makeFallBack(record.fallback()) : item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates a fall back button for given record.
|
||||
* @param record Record which fallback must be created.
|
||||
* @return PanelItem if fallback was creates successfully, otherwise null.
|
||||
*/
|
||||
@Nullable
|
||||
private PanelItem makeFallBack(@Nullable ItemTemplateRecord record)
|
||||
{
|
||||
return record == null ? null : this.makeButton(record.fallback());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method translates template record into a panel item.
|
||||
* @param record Record that must be translated.
|
||||
* @return PanelItem that contains all information from the record.
|
||||
*/
|
||||
private PanelItem makeTemplate(PanelTemplateRecord.TemplateItem record)
|
||||
{
|
||||
PanelItemBuilder itemBuilder = new PanelItemBuilder();
|
||||
|
||||
// Read icon only if it is not null.
|
||||
if (record.icon() != null)
|
||||
{
|
||||
itemBuilder.icon(record.icon().clone());
|
||||
}
|
||||
|
||||
// Read title only if it is not null.
|
||||
if (record.title() != null)
|
||||
{
|
||||
itemBuilder.name(this.user.getTranslation(record.title()));
|
||||
}
|
||||
|
||||
// Read description only if it is not null.
|
||||
if (record.description() != null)
|
||||
{
|
||||
itemBuilder.description(this.user.getTranslation(record.description()));
|
||||
}
|
||||
|
||||
// Click Handlers are managed by custom addon buttons.
|
||||
return itemBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Classes
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This record contains current slot object and map that links types with a number of slots in
|
||||
* panel with it.
|
||||
* Some buttons need information about all types, like previous/next.
|
||||
* @param slot Index of object in current panel.
|
||||
* @param amountMap Map that links types with number of objects in panel.
|
||||
*/
|
||||
public record ItemSlot(int slot, Map<String, Integer> amountMap)
|
||||
{
|
||||
/**
|
||||
* This method returns new record object with iterative slot index.
|
||||
* @return New ItemSlot object that has increased slot index by 1.
|
||||
*/
|
||||
ItemSlot nextItemSlot()
|
||||
{
|
||||
return new ItemSlot(this.slot() + 1, this.amountMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* The GUI template record.
|
||||
*/
|
||||
private final PanelTemplateRecord panelTemplate;
|
||||
|
||||
/**
|
||||
* The user who opens the GUI.
|
||||
*/
|
||||
private final User user;
|
||||
|
||||
/**
|
||||
* This map links custom types with their info object.
|
||||
*/
|
||||
private final Map<String, BiFunction<ItemTemplateRecord, ItemSlot, PanelItem>> typeCreators;
|
||||
|
||||
/**
|
||||
* Stores the item slot information for each type.
|
||||
*/
|
||||
private final Map<String, ItemSlot> typeIndex;
|
||||
|
||||
/**
|
||||
* Stores the number of items with given type in whole panel.
|
||||
*/
|
||||
private final Map<String, Integer> typeSlotMap;
|
||||
}
|
@ -3,13 +3,14 @@ package world.bentobox.bentobox.api.panels.builders;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.PanelListener;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* Builds panels
|
||||
@ -26,7 +27,7 @@ public class PanelBuilder {
|
||||
private World world;
|
||||
|
||||
public PanelBuilder name(String name) {
|
||||
this.name = ChatColor.translateAlternateColorCodes('&', name);
|
||||
this.name = Util.translateColorCodes(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,14 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
public class PanelItemBuilder {
|
||||
private ItemStack icon = new ItemStack(Material.AIR);
|
||||
@ -59,7 +60,7 @@ public class PanelItemBuilder {
|
||||
}
|
||||
|
||||
public PanelItemBuilder name(@Nullable String name) {
|
||||
this.name = name != null ? ChatColor.translateAlternateColorCodes('&', name) : null;
|
||||
this.name = name != null ? Util.translateColorCodes(name) : null;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,203 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.builders;
|
||||
|
||||
|
||||
import org.bukkit.World;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.PanelListener;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord;
|
||||
import world.bentobox.bentobox.api.panels.reader.TemplateReader;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
|
||||
|
||||
/**
|
||||
* Builds {@link TemplatedPanel}'s
|
||||
* @author BONNe
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public class TemplatedPanelBuilder
|
||||
{
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Builder
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds the template that must be loaded for Template panel builder.
|
||||
*
|
||||
* @param guiName the gui name
|
||||
* @param dataFolder the data folder
|
||||
* @return the template panel builder
|
||||
*/
|
||||
public TemplatedPanelBuilder template(String guiName, File dataFolder)
|
||||
{
|
||||
this.panelTemplate = TemplateReader.readTemplatePanel(guiName, dataFolder);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the user for template panel builder.
|
||||
*
|
||||
* @param user the user
|
||||
* @return the template panel builder
|
||||
*/
|
||||
public TemplatedPanelBuilder user(User user)
|
||||
{
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the world for template panel builder.
|
||||
*
|
||||
* @param world the world
|
||||
* @return the template panel builder
|
||||
*/
|
||||
public TemplatedPanelBuilder world(World world)
|
||||
{
|
||||
this.world = world;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the panel listener for template panel builder.
|
||||
*
|
||||
* @param listener the listener
|
||||
* @return the template panel builder
|
||||
*/
|
||||
public TemplatedPanelBuilder listener(PanelListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers new button type builder for template panel builder.
|
||||
*
|
||||
* @param type the type
|
||||
* @param buttonCreator the button creator
|
||||
* @return the template panel builder
|
||||
*/
|
||||
public TemplatedPanelBuilder registerTypeBuilder(String type, BiFunction<ItemTemplateRecord, TemplatedPanel.ItemSlot, PanelItem> buttonCreator)
|
||||
{
|
||||
this.objectCreatorMap.put(type, buttonCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build templated panel.
|
||||
*
|
||||
* @return the templated panel
|
||||
*/
|
||||
public TemplatedPanel build()
|
||||
{
|
||||
return new TemplatedPanel(this);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Getters
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Gets panel template.
|
||||
*
|
||||
* @return the panel template
|
||||
*/
|
||||
public PanelTemplateRecord getPanelTemplate()
|
||||
{
|
||||
return this.panelTemplate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets user.
|
||||
*
|
||||
* @return the user
|
||||
*/
|
||||
public User getUser()
|
||||
{
|
||||
return this.user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets world.
|
||||
*
|
||||
* @return the world
|
||||
*/
|
||||
public World getWorld()
|
||||
{
|
||||
return this.world;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets listener.
|
||||
*
|
||||
* @return the listener
|
||||
*/
|
||||
public PanelListener getListener()
|
||||
{
|
||||
return this.listener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets object creator map.
|
||||
*
|
||||
* @return the object creator map
|
||||
*/
|
||||
public Map<String, BiFunction<ItemTemplateRecord, TemplatedPanel.ItemSlot, PanelItem>> getObjectCreatorMap()
|
||||
{
|
||||
return this.objectCreatorMap;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* The GUI template record.
|
||||
*/
|
||||
private PanelTemplateRecord panelTemplate;
|
||||
|
||||
/**
|
||||
* The user who opens the GUI.
|
||||
*/
|
||||
private User user;
|
||||
|
||||
/**
|
||||
* The world where GUI operates.
|
||||
*/
|
||||
private World world;
|
||||
|
||||
/**
|
||||
* Panel Listener
|
||||
*/
|
||||
private PanelListener listener;
|
||||
|
||||
/**
|
||||
* Map that links objects with their panel item creators.
|
||||
*/
|
||||
private final Map<String, BiFunction<ItemTemplateRecord, TemplatedPanel.ItemSlot, PanelItem>> objectCreatorMap = new HashMap<>();
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* API for GUI panel creation and usage.
|
||||
*
|
||||
* <p>
|
||||
* BentoBox provides an API that enables Addon developers to display a GUI.
|
||||
* There is the basic Panel and the more advanced TabbedPanel. Both use Builders
|
||||
* to make them. For examples, look at the Settings classes.
|
||||
* </p>
|
||||
* <p>
|
||||
* Clicking on a panel item is handled by classes that implement the PanelListener interface.
|
||||
* When a click is made, the listener is called with various parameters available. It is possible
|
||||
* to have an overall listener for the whole panel and also individual listeners just for the
|
||||
* icon that was clicked.
|
||||
* <p>
|
||||
* The tabbed panel contains Tabs that are accessible via icons at the top of the panel.
|
||||
* </p>
|
||||
*
|
||||
* @author tastybento
|
||||
* @since 1.7.0
|
||||
*/
|
||||
package world.bentobox.bentobox.api.panels;
|
@ -0,0 +1,89 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This Record contains all necessary information about Item Template that can be used to craft panel item.
|
||||
*
|
||||
* @param icon ItemStack of the Item
|
||||
* @param title Title of the item
|
||||
* @param description Lore message of the item
|
||||
* @param actions List of Actions for a button
|
||||
* @param dataMap DataMap that links additional objects for a button.
|
||||
* @param fallback FallBack item if current one is not possible to generate.
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public record ItemTemplateRecord(@Nullable ItemStack icon,
|
||||
@Nullable String title,
|
||||
@Nullable String description,
|
||||
@NonNull List<ActionRecords> actions,
|
||||
@NonNull Map<String, Object> dataMap,
|
||||
@Nullable ItemTemplateRecord fallback)
|
||||
{
|
||||
/**
|
||||
* Instantiates a new Item template record without actions and data map.
|
||||
*
|
||||
* @param icon the icon
|
||||
* @param title the title
|
||||
* @param description the description
|
||||
* @param fallback the fallback
|
||||
*/
|
||||
public ItemTemplateRecord(ItemStack icon, String title, String description, ItemTemplateRecord fallback)
|
||||
{
|
||||
this(icon, title, description, new ArrayList<>(6), new HashMap<>(0), fallback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method adds given object associated with key into data map.
|
||||
* @param key Key value of object.
|
||||
* @param data Data that is associated with a key.
|
||||
*/
|
||||
public void addData(String key, Object data)
|
||||
{
|
||||
this.dataMap.put(key, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add action to the actions list.
|
||||
*
|
||||
* @param actionData the action data
|
||||
*/
|
||||
public void addAction(ActionRecords actionData)
|
||||
{
|
||||
this.actions.add(actionData);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Classes
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* The Action Records holds data about each action.
|
||||
*
|
||||
* @param clickType the click type
|
||||
* @param actionType the string that represents action type
|
||||
* @param content the content of the action
|
||||
* @param tooltip the tooltip of action
|
||||
*/
|
||||
public record ActionRecords(ClickType clickType, String actionType, String content, String tooltip) {}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
|
||||
|
||||
/**
|
||||
* This is template object for the panel reader. It contains data that can exist in the panel.
|
||||
* PanelBuilder will use this to build panel.
|
||||
*
|
||||
* @param type the type of GUI
|
||||
* @param title the title of GUI
|
||||
* @param border the border block for GUI
|
||||
* @param background the background block for GUI.
|
||||
* @param forcedRows the array of boolean that indicate which rows must be force loaded.
|
||||
* @param content The 2D array of ItemTemplateRecords
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public record PanelTemplateRecord(Panel.Type type,
|
||||
@Nullable String title,
|
||||
@Nullable TemplateItem border,
|
||||
@Nullable TemplateItem background,
|
||||
boolean[] forcedRows,
|
||||
@NonNull ItemTemplateRecord[][] content)
|
||||
{
|
||||
/**
|
||||
* Instantiates a new Panel template record with empty content.
|
||||
*
|
||||
* @param type the type
|
||||
* @param title the title
|
||||
* @param border the border
|
||||
* @param background the background
|
||||
* @param forcedRows the forced rows array
|
||||
*/
|
||||
public PanelTemplateRecord(Panel.Type type, String title, TemplateItem border, TemplateItem background, boolean[] forcedRows)
|
||||
{
|
||||
this(type, title, border, background, forcedRows, new ItemTemplateRecord[6][9]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method adds give item template record in given slot.
|
||||
* @param rowIndex row index of content array
|
||||
* @param columnIndex column index of content array.
|
||||
* @param panelItemTemplate item template record that must be added.
|
||||
*/
|
||||
public void addButtonTemplate(int rowIndex, int columnIndex, ItemTemplateRecord panelItemTemplate)
|
||||
{
|
||||
this.content[rowIndex][columnIndex] = panelItemTemplate;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Classes
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This record contains info about border and background item.
|
||||
*/
|
||||
public record TemplateItem(ItemStack icon, String title, String description)
|
||||
{
|
||||
public TemplateItem(ItemStack icon)
|
||||
{
|
||||
this(icon, null, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,364 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
import world.bentobox.bentobox.util.ItemParser;
|
||||
|
||||
|
||||
/**
|
||||
* This class manages Template file reading, creating PanelTemplateRecord object and storing it internally.
|
||||
* This class just reads and returns given panel template. It does not create a functional panel.
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public class TemplateReader
|
||||
{
|
||||
/**
|
||||
* Read template panel panel template record.
|
||||
*
|
||||
* @param panelName the panel name
|
||||
* @param panelLocation the panel location directory
|
||||
* @return the panel template record
|
||||
*/
|
||||
public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @NonNull File panelLocation)
|
||||
{
|
||||
if (!panelLocation.exists())
|
||||
{
|
||||
// Return null because folder does not exist.
|
||||
return null;
|
||||
}
|
||||
|
||||
File file = new File(panelLocation, panelName.endsWith(".yml") ? panelName : panelName + ".yml");
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
// Return as file does not exist.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if panel is already crafted.
|
||||
if (TemplateReader.loadedPanels.containsKey(file.getAbsolutePath()))
|
||||
{
|
||||
return TemplateReader.loadedPanels.get(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
PanelTemplateRecord record;
|
||||
|
||||
try
|
||||
{
|
||||
// Load config
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.load(file);
|
||||
// Read panel
|
||||
record = readPanelTemplate(config.getConfigurationSection(panelName));
|
||||
// Put panel into memory
|
||||
TemplateReader.loadedPanels.put(file.getAbsolutePath(), record);
|
||||
}
|
||||
catch (IOException | InvalidConfigurationException e)
|
||||
{
|
||||
record = null;
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method reads panel template from given configuration section.
|
||||
* @param configurationSection Section that contains panel template data.
|
||||
* @return Panel Template.
|
||||
*/
|
||||
private static PanelTemplateRecord readPanelTemplate(@Nullable ConfigurationSection configurationSection)
|
||||
{
|
||||
if (configurationSection == null)
|
||||
{
|
||||
// No data to return.
|
||||
return null;
|
||||
}
|
||||
|
||||
String title = configurationSection.getString("title");
|
||||
Panel.Type type =
|
||||
Enums.getIfPresent(Panel.Type.class, configurationSection.getString("type", "INVENTORY")).
|
||||
or(Panel.Type.INVENTORY);
|
||||
|
||||
PanelTemplateRecord.TemplateItem borderItem = null;
|
||||
|
||||
// Read Border Icon.
|
||||
if (configurationSection.isConfigurationSection("border"))
|
||||
{
|
||||
// Process border icon if it contains more options.
|
||||
ConfigurationSection borderSection = configurationSection.getConfigurationSection("border");
|
||||
|
||||
if (borderSection != null)
|
||||
{
|
||||
borderItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((borderSection.getString("icon", Material.AIR.name()))),
|
||||
borderSection.getString("title", null),
|
||||
borderSection.getString("description", null));
|
||||
}
|
||||
}
|
||||
else if (configurationSection.isString("border"))
|
||||
{
|
||||
// Process border icon if it contains only icon.
|
||||
|
||||
borderItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((configurationSection.getString("border", Material.AIR.name()))));
|
||||
}
|
||||
|
||||
PanelTemplateRecord.TemplateItem backgroundItem = null;
|
||||
|
||||
// Read Background block
|
||||
if (configurationSection.isConfigurationSection("background"))
|
||||
{
|
||||
// Process border icon if it contains more options.
|
||||
ConfigurationSection backgroundSection = configurationSection.getConfigurationSection("background");
|
||||
|
||||
if (backgroundSection != null)
|
||||
{
|
||||
backgroundItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((backgroundSection.getString("icon", Material.AIR.name()))),
|
||||
backgroundSection.getString("title", null),
|
||||
backgroundSection.getString("description", null));
|
||||
}
|
||||
}
|
||||
else if (configurationSection.isString("background"))
|
||||
{
|
||||
// Process background icon if it contains only icon.
|
||||
|
||||
backgroundItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((configurationSection.getString("background", Material.AIR.name()))));
|
||||
}
|
||||
|
||||
// Read reusable
|
||||
Map<String, ItemTemplateRecord> panelItemDataMap = new HashMap<>();
|
||||
ConfigurationSection reusable = configurationSection.getConfigurationSection("reusable");
|
||||
|
||||
if (reusable != null)
|
||||
{
|
||||
// Add all reusables to the local storage.
|
||||
reusable.getKeys(false).forEach(key ->
|
||||
readPanelItemTemplate(reusable.getConfigurationSection(key), key, panelItemDataMap));
|
||||
}
|
||||
|
||||
// Read content
|
||||
boolean[] forcedRows = readForcedRows(configurationSection);
|
||||
|
||||
// Create template record.
|
||||
PanelTemplateRecord template = new PanelTemplateRecord(type, title, borderItem, backgroundItem, forcedRows);
|
||||
|
||||
// Read content
|
||||
ConfigurationSection content = configurationSection.getConfigurationSection("content");
|
||||
|
||||
if (content == null)
|
||||
{
|
||||
// Return empty template.
|
||||
return template;
|
||||
}
|
||||
|
||||
for (int rowIndex = 0; rowIndex < 6; rowIndex++)
|
||||
{
|
||||
// Read each line.
|
||||
if (content.isConfigurationSection(String.valueOf(rowIndex + 1)))
|
||||
{
|
||||
ConfigurationSection line = content.getConfigurationSection(String.valueOf(rowIndex + 1));
|
||||
|
||||
if (line != null)
|
||||
{
|
||||
// Populate existing lines with items.
|
||||
for (int columnIndex = 0; columnIndex < 9; columnIndex++)
|
||||
{
|
||||
if (line.isConfigurationSection(String.valueOf(columnIndex + 1)))
|
||||
{
|
||||
// If it contains a section, then build a new button template from it.
|
||||
template.addButtonTemplate(rowIndex,
|
||||
columnIndex,
|
||||
readPanelItemTemplate(line.getConfigurationSection(String.valueOf(columnIndex + 1))));
|
||||
}
|
||||
else if (line.isString(String.valueOf(columnIndex + 1)))
|
||||
{
|
||||
// If it contains just a single word, assume it is a reusable.
|
||||
template.addButtonTemplate(rowIndex,
|
||||
columnIndex,
|
||||
panelItemDataMap.get(line.getString(String.valueOf(columnIndex + 1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Garbage collector.
|
||||
panelItemDataMap.clear();
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method reads force shown rows that must be always displayed.
|
||||
* @param section Configuration section that contains force-shown path.
|
||||
* @return boolean array that contains which lines are force loaded.
|
||||
*/
|
||||
private static boolean[] readForcedRows(@Nullable ConfigurationSection section)
|
||||
{
|
||||
boolean[] forceShow = new boolean[6];
|
||||
|
||||
if (section != null && section.contains("force-shown"))
|
||||
{
|
||||
if (section.isInt("force-shown"))
|
||||
{
|
||||
int value = section.getInt("force-shown");
|
||||
|
||||
if (value > 0 && value < 7)
|
||||
{
|
||||
forceShow[value-1] = true;
|
||||
}
|
||||
}
|
||||
else if (section.isList("force-shown"))
|
||||
{
|
||||
section.getIntegerList("force-shown").forEach(number -> {
|
||||
if (number > 0 && number < 7)
|
||||
{
|
||||
forceShow[number-1] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return forceShow;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItemTemplate from a given configuration section.
|
||||
* @param section Section that should contain all information about the panel item template.
|
||||
* @return PanelItemTemplate that should represent button from a section.
|
||||
*/
|
||||
@Nullable
|
||||
private static ItemTemplateRecord readPanelItemTemplate(@Nullable ConfigurationSection section)
|
||||
{
|
||||
return readPanelItemTemplate(section, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItemTemplate from a given configuration section.
|
||||
* @param section Section that should contain all information about the panel item template.
|
||||
* @return PanelItemTemplate that should represent button from a section.
|
||||
*/
|
||||
@Nullable
|
||||
private static ItemTemplateRecord readPanelItemTemplate(@Nullable ConfigurationSection section,
|
||||
String itemKey,
|
||||
Map<String, ItemTemplateRecord> reusableItemMap)
|
||||
{
|
||||
if (section == null)
|
||||
{
|
||||
// No section, no item.
|
||||
return null;
|
||||
}
|
||||
|
||||
ItemTemplateRecord fallback;
|
||||
|
||||
if (section.isConfigurationSection("fallback"))
|
||||
{
|
||||
fallback = readPanelItemTemplate(section.getConfigurationSection("fallback"));
|
||||
}
|
||||
else if (section.isString("fallback") && reusableItemMap != null)
|
||||
{
|
||||
fallback = reusableItemMap.get(section.getString("fallback"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fallback = null;
|
||||
}
|
||||
|
||||
// Create Item Record
|
||||
ItemTemplateRecord itemRecord = new ItemTemplateRecord(ItemParser.parse(section.getString("icon")),
|
||||
section.getString("title", null),
|
||||
section.getString("description", null),
|
||||
fallback);
|
||||
|
||||
// Read data
|
||||
if (section.isConfigurationSection("data"))
|
||||
{
|
||||
ConfigurationSection dataSection = section.getConfigurationSection("data");
|
||||
|
||||
if (dataSection != null)
|
||||
{
|
||||
dataSection.getKeys(false).forEach(key -> itemRecord.addData(key, dataSection.get(key)));
|
||||
}
|
||||
}
|
||||
|
||||
// Read Click data
|
||||
if (section.isConfigurationSection("actions"))
|
||||
{
|
||||
ConfigurationSection actionSection = section.getConfigurationSection("actions");
|
||||
|
||||
if (actionSection != null)
|
||||
{
|
||||
actionSection.getKeys(false).forEach(actionKey -> {
|
||||
ClickType clickType = Enums.getIfPresent(ClickType.class, actionKey.toUpperCase()).orNull();
|
||||
|
||||
if (clickType != null)
|
||||
{
|
||||
ConfigurationSection actionDataSection = actionSection.getConfigurationSection(actionKey);
|
||||
|
||||
if (actionDataSection != null)
|
||||
{
|
||||
ItemTemplateRecord.ActionRecords actionData =
|
||||
new ItemTemplateRecord.ActionRecords(clickType,
|
||||
actionDataSection.getString("type"),
|
||||
actionDataSection.getString("content"),
|
||||
actionDataSection.getString("tooltip"));
|
||||
|
||||
itemRecord.addAction(actionData);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add item to the map
|
||||
if (reusableItemMap != null && itemKey != null)
|
||||
{
|
||||
reusableItemMap.put(itemKey, itemRecord);
|
||||
}
|
||||
|
||||
return itemRecord;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method clears loaded panels from the cache.
|
||||
*/
|
||||
public static void clearPanels()
|
||||
{
|
||||
loadedPanels.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This map contains already read panels and their location.
|
||||
* This improves performance for GUI opening, with a some memory usage.
|
||||
*/
|
||||
private static final Map<String, PanelTemplateRecord> loadedPanels = new HashMap<>();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* API for placeholder replacement.
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @author Poslovitch
|
||||
*/
|
||||
package world.bentobox.bentobox.api.placeholders;
|
@ -3,7 +3,7 @@ package world.bentobox.bentobox.api.placeholders.placeholderapi;
|
||||
import world.bentobox.bentobox.api.addons.Addon;
|
||||
|
||||
public class AddonPlaceholderExpansion extends BasicPlaceholderExpansion {
|
||||
private Addon addon;
|
||||
private final Addon addon;
|
||||
|
||||
public AddonPlaceholderExpansion(Addon addon) {
|
||||
this.addon = addon;
|
||||
|
@ -16,7 +16,7 @@ import world.bentobox.bentobox.api.user.User;
|
||||
*/
|
||||
abstract class BasicPlaceholderExpansion extends PlaceholderExpansion {
|
||||
@NonNull
|
||||
private Map<@NonNull String, @NonNull PlaceholderReplacer> placeholders;
|
||||
private final Map<@NonNull String, @NonNull PlaceholderReplacer> placeholders;
|
||||
|
||||
BasicPlaceholderExpansion() {
|
||||
super();
|
||||
|
@ -3,7 +3,7 @@ package world.bentobox.bentobox.api.placeholders.placeholderapi;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
|
||||
public class BentoBoxPlaceholderExpansion extends BasicPlaceholderExpansion {
|
||||
private BentoBox plugin;
|
||||
private final BentoBox plugin;
|
||||
|
||||
public BentoBoxPlaceholderExpansion(BentoBox plugin) {
|
||||
super();
|
||||
|
@ -9,7 +9,7 @@ import com.google.common.cache.LoadingCache;
|
||||
|
||||
/**
|
||||
* Utilities class that helps to avoid spamming the User with potential repeated messages
|
||||
* @author Poslovitch
|
||||
* @author Poslovitch, tastybento
|
||||
*/
|
||||
public class Notifier {
|
||||
|
||||
@ -18,17 +18,19 @@ public class Notifier {
|
||||
*/
|
||||
private static final int NOTIFICATION_DELAY = 4;
|
||||
|
||||
private record Notification(String message, long time) {}
|
||||
|
||||
private final LoadingCache<User, Notification> notificationCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(NOTIFICATION_DELAY, TimeUnit.SECONDS)
|
||||
.maximumSize(500)
|
||||
.build(
|
||||
new CacheLoader<User, Notification>() {
|
||||
new CacheLoader<>() {
|
||||
@Override
|
||||
public Notification load(User user) {
|
||||
return new Notification(null, 0);
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/**
|
||||
* Sends message to a user only if the message hasn't been sent recently
|
||||
@ -41,7 +43,7 @@ public class Notifier {
|
||||
Notification lastNotification = notificationCache.get(user);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (now >= lastNotification.getTime() + (NOTIFICATION_DELAY * 1000) || !message.equals(lastNotification.getMessage())) {
|
||||
if (now >= lastNotification.time() + (NOTIFICATION_DELAY * 1000) || !message.equals(lastNotification.message())) {
|
||||
notificationCache.put(user, new Notification(message, now));
|
||||
user.sendRawMessage(message);
|
||||
return true;
|
||||
@ -52,21 +54,4 @@ public class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
private class Notification {
|
||||
private final String message;
|
||||
private final long time;
|
||||
|
||||
private Notification(String message, long time) {
|
||||
this.message = message;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class User implements MetaDataAble {
|
||||
|
||||
private static Map<UUID, User> users = new HashMap<>();
|
||||
private static final Map<UUID, User> users = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Clears all users from the user list
|
||||
@ -136,7 +136,7 @@ public class User implements MetaDataAble {
|
||||
private static BentoBox plugin = BentoBox.getInstance();
|
||||
|
||||
@Nullable
|
||||
private Player player;
|
||||
private final Player player;
|
||||
private OfflinePlayer offlinePlayer;
|
||||
private final UUID playerUUID;
|
||||
@Nullable
|
||||
@ -410,7 +410,7 @@ public class User implements MetaDataAble {
|
||||
translation = plugin.getPlaceholdersManager().replacePlaceholders(player, translation);
|
||||
}
|
||||
|
||||
return Util.stripSpaceAfterColorCodes(ChatColor.translateAlternateColorCodes('&', translation));
|
||||
return Util.translateColorCodes(translation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,10 +618,9 @@ public class User implements MetaDataAble {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof User)) {
|
||||
if (!(obj instanceof User other)) {
|
||||
return false;
|
||||
}
|
||||
User other = (User) obj;
|
||||
if (playerUUID == null) {
|
||||
return other.playerUUID == null;
|
||||
} else return playerUUID.equals(other.playerUUID);
|
||||
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* API for BentoBox Users
|
||||
*
|
||||
* <p>
|
||||
* BentoBox has extended the Bukkit Player class to become a User with the primary reason
|
||||
* to enable localized messaging. Apart from that a User can be an OfflinePlayer, a Player,
|
||||
* or even the Console. Users are used throughout the BentoBox code base, e.g., for commands
|
||||
* instead of Players. It is possible to get a Player from a User if the User is a player.
|
||||
* </p>
|
||||
* <p>
|
||||
* Notifier is a special kind of messaging class that prevents spamming of messages to a
|
||||
* user in chat. It is useful for cases when the same message may be generated many times, e.g., in
|
||||
* a protection scenario.
|
||||
* </p>
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.user;
|
@ -63,10 +63,10 @@ public class BlueprintClipboard {
|
||||
private boolean copying;
|
||||
private int index;
|
||||
private int lastPercentage;
|
||||
private Map<Vector, List<BlueprintEntity>> bpEntities = new LinkedHashMap<>();
|
||||
private Map<Vector, BlueprintBlock> bpAttachable = new LinkedHashMap<>();
|
||||
private Map<Vector, BlueprintBlock> bpBlocks = new LinkedHashMap<>();
|
||||
private BentoBox plugin = BentoBox.getInstance();
|
||||
private final Map<Vector, List<BlueprintEntity>> bpEntities = new LinkedHashMap<>();
|
||||
private final Map<Vector, BlueprintBlock> bpAttachable = new LinkedHashMap<>();
|
||||
private final Map<Vector, BlueprintBlock> bpBlocks = new LinkedHashMap<>();
|
||||
private final BentoBox plugin = BentoBox.getInstance();
|
||||
|
||||
/**
|
||||
* Create a clipboard for blueprint
|
||||
@ -190,48 +190,7 @@ public class BlueprintClipboard {
|
||||
Vector pos = new Vector(x, y, z);
|
||||
|
||||
// Set entities
|
||||
List<BlueprintEntity> bpEnts = new ArrayList<>();
|
||||
for (LivingEntity entity: entities) {
|
||||
BlueprintEntity bpe = new BlueprintEntity();
|
||||
bpe.setType(entity.getType());
|
||||
bpe.setCustomName(entity.getCustomName());
|
||||
if (entity instanceof Villager) {
|
||||
setVillager(entity, bpe);
|
||||
}
|
||||
if (entity instanceof Colorable) {
|
||||
Colorable c = (Colorable)entity;
|
||||
if (c.getColor() != null) {
|
||||
bpe.setColor(c.getColor());
|
||||
}
|
||||
}
|
||||
if (entity instanceof Tameable) {
|
||||
bpe.setTamed(((Tameable)entity).isTamed());
|
||||
}
|
||||
if (entity instanceof ChestedHorse) {
|
||||
bpe.setChest(((ChestedHorse)entity).isCarryingChest());
|
||||
}
|
||||
// Only set if child. Most animals are adults
|
||||
if (entity instanceof Ageable && !((Ageable)entity).isAdult()) {
|
||||
bpe.setAdult(false);
|
||||
}
|
||||
if (entity instanceof AbstractHorse) {
|
||||
AbstractHorse horse = (AbstractHorse)entity;
|
||||
bpe.setDomestication(horse.getDomestication());
|
||||
bpe.setInventory(new HashMap<>());
|
||||
for (int i = 0; i < horse.getInventory().getSize(); i++) {
|
||||
ItemStack item = horse.getInventory().getItem(i);
|
||||
if (item != null) {
|
||||
bpe.getInventory().put(i, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof Horse) {
|
||||
Horse horse = (Horse)entity;
|
||||
bpe.setStyle(horse.getStyle());
|
||||
}
|
||||
bpEnts.add(bpe);
|
||||
}
|
||||
List<BlueprintEntity> bpEnts = setEntities(entities);
|
||||
// Store
|
||||
if (!bpEnts.isEmpty()) {
|
||||
bpEntities.put(pos, bpEnts);
|
||||
@ -242,22 +201,31 @@ public class BlueprintClipboard {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BlueprintBlock b = bluePrintBlock(pos, block);
|
||||
if (b != null) {
|
||||
this.bpBlocks.put(pos, b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private BlueprintBlock bluePrintBlock(Vector pos, Block block) {
|
||||
// Block state
|
||||
BlockState blockState = block.getState();
|
||||
BlueprintBlock b = new BlueprintBlock(block.getBlockData().getAsString());
|
||||
// Biome
|
||||
b.setBiome(block.getBiome());
|
||||
// Signs
|
||||
if (blockState instanceof Sign) {
|
||||
Sign sign = (Sign)blockState;
|
||||
if (blockState instanceof Sign sign) {
|
||||
b.setSignLines(Arrays.asList(sign.getLines()));
|
||||
b.setGlowingText(sign.isGlowingText());
|
||||
}
|
||||
// Set block data
|
||||
if (blockState.getData() instanceof Attachable) {
|
||||
// Placeholder for attachment
|
||||
bpBlocks.put(pos, new BlueprintBlock("minecraft:air"));
|
||||
bpAttachable.put(pos, b);
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (block.getType().equals(Material.BEDROCK)) {
|
||||
@ -272,9 +240,8 @@ public class BlueprintClipboard {
|
||||
}
|
||||
|
||||
// Chests
|
||||
if (blockState instanceof InventoryHolder) {
|
||||
if (blockState instanceof InventoryHolder ih) {
|
||||
b.setInventory(new HashMap<>());
|
||||
InventoryHolder ih = (InventoryHolder)blockState;
|
||||
for (int i = 0; i < ih.getInventory().getSize(); i++) {
|
||||
ItemStack item = ih.getInventory().getItem(i);
|
||||
if (item != null) {
|
||||
@ -283,17 +250,8 @@ public class BlueprintClipboard {
|
||||
}
|
||||
}
|
||||
|
||||
if (blockState instanceof CreatureSpawner) {
|
||||
CreatureSpawner spawner = (CreatureSpawner)blockState;
|
||||
BlueprintCreatureSpawner cs = new BlueprintCreatureSpawner();
|
||||
cs.setSpawnedType(spawner.getSpawnedType());
|
||||
cs.setDelay(spawner.getDelay());
|
||||
cs.setMaxNearbyEntities(spawner.getMaxNearbyEntities());
|
||||
cs.setMaxSpawnDelay(spawner.getMaxSpawnDelay());
|
||||
cs.setMinSpawnDelay(spawner.getMinSpawnDelay());
|
||||
cs.setRequiredPlayerRange(spawner.getRequiredPlayerRange());
|
||||
cs.setSpawnRange(spawner.getSpawnRange());
|
||||
b.setCreatureSpawner(cs);
|
||||
if (blockState instanceof CreatureSpawner spawner) {
|
||||
b.setCreatureSpawner(getSpawner(spawner));
|
||||
}
|
||||
|
||||
// Banners
|
||||
@ -301,8 +259,62 @@ public class BlueprintClipboard {
|
||||
b.setBannerPatterns(((Banner) blockState).getPatterns());
|
||||
}
|
||||
|
||||
this.bpBlocks.put(pos, b);
|
||||
return true;
|
||||
return b;
|
||||
}
|
||||
|
||||
private BlueprintCreatureSpawner getSpawner(CreatureSpawner spawner) {
|
||||
BlueprintCreatureSpawner cs = new BlueprintCreatureSpawner();
|
||||
cs.setSpawnedType(spawner.getSpawnedType());
|
||||
cs.setDelay(spawner.getDelay());
|
||||
cs.setMaxNearbyEntities(spawner.getMaxNearbyEntities());
|
||||
cs.setMaxSpawnDelay(spawner.getMaxSpawnDelay());
|
||||
cs.setMinSpawnDelay(spawner.getMinSpawnDelay());
|
||||
cs.setRequiredPlayerRange(spawner.getRequiredPlayerRange());
|
||||
cs.setSpawnRange(spawner.getSpawnRange());
|
||||
return cs;
|
||||
}
|
||||
|
||||
private List<BlueprintEntity> setEntities(Collection<LivingEntity> entities) {
|
||||
List<BlueprintEntity> bpEnts = new ArrayList<>();
|
||||
for (LivingEntity entity: entities) {
|
||||
BlueprintEntity bpe = new BlueprintEntity();
|
||||
bpe.setType(entity.getType());
|
||||
bpe.setCustomName(entity.getCustomName());
|
||||
if (entity instanceof Villager) {
|
||||
setVillager(entity, bpe);
|
||||
}
|
||||
if (entity instanceof Colorable c) {
|
||||
if (c.getColor() != null) {
|
||||
bpe.setColor(c.getColor());
|
||||
}
|
||||
}
|
||||
if (entity instanceof Tameable) {
|
||||
bpe.setTamed(((Tameable)entity).isTamed());
|
||||
}
|
||||
if (entity instanceof ChestedHorse) {
|
||||
bpe.setChest(((ChestedHorse)entity).isCarryingChest());
|
||||
}
|
||||
// Only set if child. Most animals are adults
|
||||
if (entity instanceof Ageable && !((Ageable)entity).isAdult()) {
|
||||
bpe.setAdult(false);
|
||||
}
|
||||
if (entity instanceof AbstractHorse horse) {
|
||||
bpe.setDomestication(horse.getDomestication());
|
||||
bpe.setInventory(new HashMap<>());
|
||||
for (int i = 0; i < horse.getInventory().getSize(); i++) {
|
||||
ItemStack item = horse.getInventory().getItem(i);
|
||||
if (item != null) {
|
||||
bpe.getInventory().put(i, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof Horse horse) {
|
||||
bpe.setStyle(horse.getStyle());
|
||||
}
|
||||
bpEnts.add(bpe);
|
||||
}
|
||||
return bpEnts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,7 +13,6 @@ import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
@ -73,7 +72,7 @@ public class BlueprintPaster {
|
||||
|
||||
private static final Map<String, String> BLOCK_CONVERSION = ImmutableMap.of("sign", "oak_sign", "wall_sign", "oak_wall_sign");
|
||||
|
||||
private BentoBox plugin;
|
||||
private final BentoBox plugin;
|
||||
// The minimum block position (x,y,z)
|
||||
private Location pos1;
|
||||
// The maximum block position (x,y,z)
|
||||
@ -86,19 +85,19 @@ public class BlueprintPaster {
|
||||
* The Blueprint to paste.
|
||||
*/
|
||||
@NonNull
|
||||
private Blueprint blueprint;
|
||||
private final Blueprint blueprint;
|
||||
|
||||
/**
|
||||
* The Location to paste to.
|
||||
*/
|
||||
@NonNull
|
||||
private Location location;
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* Island related to this paste, may be null.
|
||||
*/
|
||||
@Nullable
|
||||
private Island island;
|
||||
private final Island island;
|
||||
|
||||
/**
|
||||
* Paste a clipboard to a location and run task
|
||||
@ -291,37 +290,39 @@ public class BlueprintPaster {
|
||||
// Get the block state
|
||||
BlockState bs = block.getState();
|
||||
// Signs
|
||||
if (bs instanceof org.bukkit.block.Sign) {
|
||||
writeSign(block, bpBlock.getSignLines());
|
||||
if (bs instanceof org.bukkit.block.Sign sign) {
|
||||
writeSign(block, bpBlock.getSignLines(), bpBlock.isGlowingText());
|
||||
}
|
||||
// Chests, in general
|
||||
if (bs instanceof InventoryHolder) {
|
||||
Inventory ih = ((InventoryHolder)bs).getInventory();
|
||||
// Double chests are pasted as two blocks so inventory is filled twice. This code stops over filling for the first block.
|
||||
// Double chests are pasted as two blocks so inventory is filled twice.
|
||||
// This code stops over-filling for the first block.
|
||||
bpBlock.getInventory().forEach(ih::setItem);
|
||||
}
|
||||
// Mob spawners
|
||||
if (bs instanceof CreatureSpawner) {
|
||||
CreatureSpawner spawner = ((CreatureSpawner) bs);
|
||||
BlueprintCreatureSpawner s = bpBlock.getCreatureSpawner();
|
||||
spawner.setSpawnedType(s.getSpawnedType());
|
||||
spawner.setMaxNearbyEntities(s.getMaxNearbyEntities());
|
||||
spawner.setMaxSpawnDelay(s.getMaxSpawnDelay());
|
||||
spawner.setMinSpawnDelay(s.getMinSpawnDelay());
|
||||
spawner.setDelay(s.getDelay());
|
||||
spawner.setRequiredPlayerRange(s.getRequiredPlayerRange());
|
||||
spawner.setSpawnRange(s.getSpawnRange());
|
||||
bs.update(true, false);
|
||||
if (bs instanceof CreatureSpawner spawner) {
|
||||
setSpawner(spawner, bpBlock.getCreatureSpawner());
|
||||
}
|
||||
// Banners
|
||||
if (bs instanceof Banner && bpBlock.getBannerPatterns() != null) {
|
||||
Banner banner = (Banner) bs;
|
||||
if (bs instanceof Banner banner && bpBlock.getBannerPatterns() != null) {
|
||||
bpBlock.getBannerPatterns().removeIf(Objects::isNull);
|
||||
banner.setPatterns(bpBlock.getBannerPatterns());
|
||||
banner.update(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSpawner(CreatureSpawner spawner, BlueprintCreatureSpawner s) {
|
||||
spawner.setSpawnedType(s.getSpawnedType());
|
||||
spawner.setMaxNearbyEntities(s.getMaxNearbyEntities());
|
||||
spawner.setMaxSpawnDelay(s.getMaxSpawnDelay());
|
||||
spawner.setMinSpawnDelay(s.getMinSpawnDelay());
|
||||
spawner.setDelay(s.getDelay());
|
||||
spawner.setRequiredPlayerRange(s.getRequiredPlayerRange());
|
||||
spawner.setSpawnRange(s.getSpawnRange());
|
||||
spawner.update(true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets any entity that is in this location
|
||||
* @param location - location
|
||||
@ -386,7 +387,7 @@ public class BlueprintPaster {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSign(final Block block, final List<String> lines) {
|
||||
private void writeSign(final Block block, final List<String> lines, boolean glow) {
|
||||
BlockFace bf;
|
||||
if (block.getType().name().contains("WALL_SIGN")) {
|
||||
WallSign wallSign = (WallSign)block.getBlockData();
|
||||
@ -416,7 +417,7 @@ public class BlueprintPaster {
|
||||
// Get the addon that is operating in this world
|
||||
String addonName = plugin.getIWM().getAddon(island.getWorld()).map(addon -> addon.getDescription().getName().toLowerCase(Locale.ENGLISH)).orElse("");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s.setLine(i, ChatColor.translateAlternateColorCodes('&', plugin.getLocalesManager().getOrDefault(User.getInstance(island.getOwner()),
|
||||
s.setLine(i, Util.translateColorCodes(plugin.getLocalesManager().getOrDefault(User.getInstance(island.getOwner()),
|
||||
addonName + ".sign.line" + i,"").replace(TextVariables.NAME, name)));
|
||||
}
|
||||
} else {
|
||||
@ -425,6 +426,7 @@ public class BlueprintPaster {
|
||||
s.setLine(i, lines.get(i));
|
||||
}
|
||||
}
|
||||
s.setGlowingText(glow);
|
||||
// Update the sign
|
||||
s.update();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package world.bentobox.bentobox.blueprints.conversation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.conversations.ConversationContext;
|
||||
import org.bukkit.conversations.Prompt;
|
||||
import org.bukkit.conversations.StringPrompt;
|
||||
@ -13,6 +12,8 @@ import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* Collects a description
|
||||
@ -22,8 +23,8 @@ import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
|
||||
public class DescriptionPrompt extends StringPrompt {
|
||||
|
||||
private static final String DESCRIPTION = "description";
|
||||
private GameModeAddon addon;
|
||||
private BlueprintBundle bb;
|
||||
private final GameModeAddon addon;
|
||||
private final BlueprintBundle bb;
|
||||
|
||||
public DescriptionPrompt(GameModeAddon addon, BlueprintBundle bb) {
|
||||
this.addon = addon;
|
||||
@ -57,7 +58,7 @@ public class DescriptionPrompt extends StringPrompt {
|
||||
if (context.getSessionData(DESCRIPTION) != null) {
|
||||
desc = ((List<String>) context.getSessionData(DESCRIPTION));
|
||||
}
|
||||
desc.add(ChatColor.translateAlternateColorCodes('&', input));
|
||||
desc.add(Util.translateColorCodes(input));
|
||||
context.setSessionData(DESCRIPTION, desc);
|
||||
return this;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ import world.bentobox.bentobox.panels.BlueprintManagementPanel;
|
||||
|
||||
public class DescriptionSuccessPrompt extends MessagePrompt {
|
||||
|
||||
private GameModeAddon addon;
|
||||
private BlueprintBundle bb;
|
||||
private final GameModeAddon addon;
|
||||
private final BlueprintBundle bb;
|
||||
|
||||
/**
|
||||
* @param addon game mode addon
|
||||
|
@ -15,12 +15,14 @@ import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.blueprints.Blueprint;
|
||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
public class NamePrompt extends StringPrompt {
|
||||
|
||||
private GameModeAddon addon;
|
||||
private final GameModeAddon addon;
|
||||
@Nullable
|
||||
private BlueprintBundle bb;
|
||||
private final BlueprintBundle bb;
|
||||
@Nullable
|
||||
private Blueprint bp;
|
||||
|
||||
@ -45,7 +47,7 @@ public class NamePrompt extends StringPrompt {
|
||||
public Prompt acceptInput(ConversationContext context, String input) {
|
||||
User user = User.getInstance((Player)context.getForWhom());
|
||||
// Convert color codes
|
||||
input = ChatColor.translateAlternateColorCodes('&', input);
|
||||
input = Util.translateColorCodes(input);
|
||||
if (ChatColor.stripColor(input).length() > 32) {
|
||||
context.getForWhom().sendRawMessage("Too long");
|
||||
return this;
|
||||
|
@ -17,9 +17,9 @@ import world.bentobox.bentobox.panels.BlueprintManagementPanel;
|
||||
|
||||
public class NameSuccessPrompt extends MessagePrompt {
|
||||
|
||||
private GameModeAddon addon;
|
||||
private final GameModeAddon addon;
|
||||
private BlueprintBundle bb;
|
||||
private Blueprint bp;
|
||||
private final Blueprint bp;
|
||||
|
||||
/**
|
||||
* Handles the name processing
|
||||
@ -42,7 +42,6 @@ public class NameSuccessPrompt extends MessagePrompt {
|
||||
if (bp != null) {
|
||||
BentoBox.getInstance().getBlueprintsManager().renameBlueprint(addon, bp, name);
|
||||
new BlueprintManagementPanel(BentoBox.getInstance(), user, addon).openBB(bb);
|
||||
return user.getTranslation("commands.admin.blueprint.management.description.success");
|
||||
} else {
|
||||
// Blueprint Bundle
|
||||
if (bb == null) {
|
||||
@ -61,8 +60,8 @@ public class NameSuccessPrompt extends MessagePrompt {
|
||||
new BlueprintManagementPanel(BentoBox.getInstance(), user, addon).openPanel();
|
||||
// Set the name
|
||||
// if successfully
|
||||
return user.getTranslation("commands.admin.blueprint.management.description.success");
|
||||
}
|
||||
return user.getTranslation("commands.admin.blueprint.management.description.success");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,8 @@ public class BlueprintBlock {
|
||||
*/
|
||||
@Expose
|
||||
private List<Pattern> bannerPatterns;
|
||||
@Expose
|
||||
private boolean glowingText;
|
||||
|
||||
public BlueprintBlock(String blockData) {
|
||||
this.blockData = blockData;
|
||||
@ -124,4 +126,20 @@ public class BlueprintBlock {
|
||||
public void setBiome(Biome biome) {
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the glowingText
|
||||
*/
|
||||
public boolean isGlowingText() {
|
||||
return glowingText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param glowingText the glowingText to set
|
||||
*/
|
||||
public void setGlowingText(boolean glowingText) {
|
||||
this.glowingText = glowingText;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -75,8 +75,7 @@ public class BlueprintEntity {
|
||||
((Ageable)e).setBaby();
|
||||
}
|
||||
}
|
||||
if (e instanceof AbstractHorse) {
|
||||
AbstractHorse horse = (AbstractHorse)e;
|
||||
if (e instanceof AbstractHorse horse) {
|
||||
if (domestication != null) horse.setDomestication(domestication);
|
||||
if (inventory != null) {
|
||||
inventory.forEach(horse.getInventory()::setItem);
|
||||
|
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* This package contains non-API classes that handle Blueprints.
|
||||
*
|
||||
* Blueprints are BentoBox's version of schematics, but contain
|
||||
* additional useful info.
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.blueprints;
|
@ -49,12 +49,12 @@ public class BlueprintClipboardFormat implements ClipboardFormat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
public ClipboardReader getReader(InputStream inputStream) {
|
||||
return new BlueprintClipboardReader(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) {
|
||||
return new BlueprintClipboardWriter(outputStream);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package world.bentobox.bentobox.blueprints.worldedit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
@ -12,19 +11,19 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
|
||||
*/
|
||||
public class BlueprintClipboardReader implements ClipboardReader {
|
||||
|
||||
private InputStream inputStream;
|
||||
private final InputStream inputStream;
|
||||
|
||||
public BlueprintClipboardReader(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard read() throws IOException {
|
||||
public Clipboard read() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package world.bentobox.bentobox.blueprints.worldedit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
@ -12,18 +11,18 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
*/
|
||||
public class BlueprintClipboardWriter implements ClipboardWriter {
|
||||
|
||||
private OutputStream outputStream;
|
||||
private final OutputStream outputStream;
|
||||
|
||||
public BlueprintClipboardWriter(OutputStream outputStream) {
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
@Override
|
||||
public void write(Clipboard clipboard) throws IOException {
|
||||
public void write(Clipboard clipboard) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ public class BlueprintSchematicConverter {
|
||||
private File blueprintFile;
|
||||
|
||||
public BlueprintSchematicConverter(File blueprintFile) {
|
||||
if(!BentoBox.getInstance().getHooks().getHook("WorldEdit").isPresent()) {
|
||||
if(BentoBox.getInstance().getHooks().getHook("WorldEdit").isEmpty()) {
|
||||
BentoBox.getInstance().logError("WorldEdit must be installed to use that class !");
|
||||
return;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
|
||||
import world.bentobox.bentobox.api.panels.reader.TemplateReader;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.commands.reload.BentoBoxReloadLocalesCommand;
|
||||
import world.bentobox.bentobox.listeners.PanelListenerManager;
|
||||
@ -45,6 +46,8 @@ public class BentoBoxReloadCommand extends ConfirmableCommand {
|
||||
|
||||
// Close all open panels
|
||||
PanelListenerManager.closeAllPanels();
|
||||
// Clear all template panels.
|
||||
TemplateReader.clearPanels();
|
||||
|
||||
// Reload settings
|
||||
getPlugin().loadSettings();
|
||||
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* The package contains non-API commands for BentoBox itself.
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.commands;
|
@ -21,8 +21,8 @@ import world.bentobox.bentobox.api.addons.Addon;
|
||||
*/
|
||||
public class Database<T> {
|
||||
|
||||
private AbstractDatabaseHandler<T> handler;
|
||||
private Logger logger;
|
||||
private final AbstractDatabaseHandler<T> handler;
|
||||
private final Logger logger;
|
||||
private static DatabaseSetup databaseSetup = DatabaseSetup.getDatabase();
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ import world.bentobox.bentobox.database.DatabaseConnector;
|
||||
*/
|
||||
public abstract class AbstractJSONDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
||||
|
||||
private Gson gson;
|
||||
private final Gson gson;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -6,7 +6,7 @@ import world.bentobox.bentobox.database.DatabaseSetup;
|
||||
|
||||
public class JSONDatabase implements DatabaseSetup {
|
||||
|
||||
private JSONDatabaseConnector connector = new JSONDatabaseConnector(BentoBox.getInstance());
|
||||
private final JSONDatabaseConnector connector = new JSONDatabaseConnector(BentoBox.getInstance());
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see world.bentobox.bentobox.database.DatabaseSetup#getHandler(java.lang.Class)
|
||||
|
@ -23,11 +23,11 @@ public class JSONDatabaseConnector implements DatabaseConnector {
|
||||
@NonNull
|
||||
public String getUniqueId(String tableName) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
File file = new File(dataFolder, tableName + File.separator + uuid.toString() + JSON);
|
||||
File file = new File(dataFolder, tableName + File.separator + uuid + JSON);
|
||||
int limit = 0;
|
||||
while (file.exists() && limit++ < MAX_LOOPS) {
|
||||
uuid = UUID.randomUUID();
|
||||
file = new File(dataFolder, tableName + File.separator + uuid.toString() + JSON);
|
||||
file = new File(dataFolder, tableName + File.separator + uuid + JSON);
|
||||
}
|
||||
return uuid.toString();
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import world.bentobox.bentobox.api.flags.Flag;
|
||||
|
||||
public class FlagTypeAdapter extends TypeAdapter<Flag> {
|
||||
|
||||
private BentoBox plugin;
|
||||
private final BentoBox plugin;
|
||||
|
||||
public FlagTypeAdapter(BentoBox plugin) {
|
||||
this.plugin = plugin;
|
||||
@ -42,7 +42,7 @@ public class FlagTypeAdapter extends TypeAdapter<Flag> {
|
||||
// Flags can end up null if an addon that created one is removed or if a flag name was changed
|
||||
if (f == null) {
|
||||
// Create a temporary flag with a unique key. It will be immediately deleted after loading
|
||||
f = new Flag.Builder("NULL_FLAG_"+ UUID.randomUUID().toString(), Material.STONE).build();
|
||||
f = new Flag.Builder("NULL_FLAG_"+ UUID.randomUUID(), Material.STONE).build();
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* These are GSON adapters used to serialize and deserialize various data types.
|
||||
* <p>
|
||||
* The {@link world.bentobox.bentobox.database.json.adapters.BukkitObjectTypeAdapter}
|
||||
* is a catch-all adapter that uses the built-in Bukkit serialization capabilities. Before
|
||||
* we knew about this, there were other ones built, like for Location, that have to remain
|
||||
* for backwards compatibility reasons.
|
||||
* </p>
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.database.json.adapters;
|
@ -40,7 +40,7 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
private static final String MONGO_ID = "_id";
|
||||
|
||||
private MongoCollection<Document> collection;
|
||||
private DatabaseConnector dbConnecter;
|
||||
private final DatabaseConnector dbConnecter;
|
||||
|
||||
/**
|
||||
* Handles the connection to the database and creation of the initial database schema (tables) for
|
||||
@ -142,12 +142,11 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
if (!(instance instanceof DataObject dataObj)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
DataObject dataObj = (DataObject)instance;
|
||||
try {
|
||||
Gson gson = getGson();
|
||||
String toStore = gson.toJson(instance);
|
||||
|
@ -1,8 +1,6 @@
|
||||
package world.bentobox.bentobox.database.objects;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -23,7 +21,6 @@ import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -37,7 +34,6 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.logs.LogEntry;
|
||||
import world.bentobox.bentobox.api.metadata.MetaDataAble;
|
||||
import world.bentobox.bentobox.api.metadata.MetaDataValue;
|
||||
@ -49,6 +45,7 @@ import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Pair;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
@ -1080,71 +1077,21 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* Shows info of this island to this user.
|
||||
* @param user the User who is requesting it
|
||||
* @return always true
|
||||
* @deprecated Use {@link IslandInfo#showInfo(User) instead}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean showInfo(User user) {
|
||||
BentoBox plugin = BentoBox.getInstance();
|
||||
user.sendMessage("commands.admin.info.title");
|
||||
user.sendMessage("commands.admin.info.island-uuid", "[uuid]", this.getUniqueId());
|
||||
if (getOwner() == null) {
|
||||
user.sendMessage("commands.admin.info.unowned");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.info.owner", "[owner]", plugin.getPlayers().getName(getOwner()), "[uuid]", getOwner().toString());
|
||||
|
||||
// Fixes #getLastPlayed() returning 0 when it is the owner's first connection.
|
||||
long lastPlayed = (Bukkit.getServer().getOfflinePlayer(getOwner()).getLastPlayed() != 0) ?
|
||||
Bukkit.getServer().getOfflinePlayer(getOwner()).getLastPlayed() : Bukkit.getServer().getOfflinePlayer(getOwner()).getFirstPlayed();
|
||||
String formattedDate;
|
||||
try {
|
||||
String dateTimeFormat = plugin.getLocalesManager().get("commands.admin.info.last-login-date-time-format");
|
||||
formattedDate = new SimpleDateFormat(dateTimeFormat).format(new Date(lastPlayed));
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {
|
||||
formattedDate = new Date(lastPlayed).toString();
|
||||
}
|
||||
user.sendMessage("commands.admin.info.last-login","[date]", formattedDate);
|
||||
|
||||
user.sendMessage("commands.admin.info.deaths", "[number]", String.valueOf(plugin.getPlayers().getDeaths(getWorld(), getOwner())));
|
||||
String resets = String.valueOf(plugin.getPlayers().getResets(getWorld(), getOwner()));
|
||||
String total = plugin.getIWM().getResetLimit(getWorld()) < 0 ? "Unlimited" : String.valueOf(plugin.getIWM().getResetLimit(getWorld()));
|
||||
user.sendMessage("commands.admin.info.resets-left", "[number]", resets, "[total]", total);
|
||||
// Show team members
|
||||
showMembers(user);
|
||||
}
|
||||
Vector location = getProtectionCenter().toVector();
|
||||
user.sendMessage("commands.admin.info.island-protection-center", TextVariables.XYZ, Util.xyz(location));
|
||||
user.sendMessage("commands.admin.info.island-center", TextVariables.XYZ, Util.xyz(getCenter().toVector()));
|
||||
user.sendMessage("commands.admin.info.island-coords", "[xz1]", Util.xyz(new Vector(this.getMinX(), 0, getMinZ())), "[xz2]", Util.xyz(new Vector(this.getMaxX(), 0, getMaxZ())));
|
||||
user.sendMessage("commands.admin.info.protection-range", "[range]", String.valueOf(getProtectionRange()));
|
||||
user.sendMessage("commands.admin.info.max-protection-range", "[range]", String.valueOf(getMaxEverProtectionRange()));
|
||||
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(new Vector(this.getMinProtectedX(), 0, getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(this.getMaxProtectedX(), 0, getMaxProtectedZ())));
|
||||
if (spawn) {
|
||||
user.sendMessage("commands.admin.info.is-spawn");
|
||||
}
|
||||
if (!getBanned().isEmpty()) {
|
||||
user.sendMessage("commands.admin.info.banned-players");
|
||||
getBanned().forEach(u -> user.sendMessage("commands.admin.info.banned-format", TextVariables.NAME, plugin.getPlayers().getName(u)));
|
||||
}
|
||||
if (getPurgeProtected()) {
|
||||
user.sendMessage("commands.admin.info.purge-protected");
|
||||
}
|
||||
return true;
|
||||
return new IslandInfo(this).showInfo(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the members of this island to this user.
|
||||
* @param user the User who is requesting it
|
||||
* @deprecated Use {@link IslandInfo#showMembers(User) instead}
|
||||
*/
|
||||
@Deprecated
|
||||
public void showMembers(User user) {
|
||||
BentoBox plugin = BentoBox.getInstance();
|
||||
user.sendMessage("commands.admin.info.team-members-title");
|
||||
members.forEach((u, i) -> {
|
||||
if (owner.equals(u)) {
|
||||
user.sendMessage("commands.admin.info.team-owner-format", TextVariables.NAME, plugin.getPlayers().getName(u)
|
||||
, "[rank]", user.getTranslation(plugin.getRanksManager().getRank(i)));
|
||||
} else if (i > RanksManager.VISITOR_RANK){
|
||||
user.sendMessage("commands.admin.info.team-member-format", TextVariables.NAME, plugin.getPlayers().getName(u)
|
||||
, "[rank]", user.getTranslation(plugin.getRanksManager().getRank(i)));
|
||||
}
|
||||
});
|
||||
new IslandInfo(this).showMembers(user);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1346,7 +1293,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @param flag - Flag to cooldown
|
||||
*/
|
||||
public void setCooldown(Flag flag) {
|
||||
cooldowns.put(flag, flag.getCooldown() * 1000 + System.currentTimeMillis());
|
||||
cooldowns.put(flag, flag.getCooldown() * 1000L + System.currentTimeMillis());
|
||||
setChanged();
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user