From afad146bd236d4023030d0a367af64781f4a7521 Mon Sep 17 00:00:00 2001 From: CJ Burkey Date: Sun, 18 Aug 2024 18:40:35 -0400 Subject: [PATCH] Bring over most changes from v0.0.26 branch --- .../com/cjburkey/claimchunk/ClaimChunk.java | 5 + .../cjburkey/claimchunk/ClaimChunkConfig.java | 33 +++ .../claimchunk/access/CCPermFlags.java | 21 +- .../claimchunk/chunk/ChunkHandler.java | 10 + .../cjburkey/claimchunk/cmd/MainHandler.java | 12 +- .../event/PlayerMovementHandler.java | 3 +- .../cjburkey/claimchunk/gui/CCGuiHandler.java | 89 ++++++++ .../cjburkey/claimchunk/gui/CCOpenGui.java | 5 + .../claimchunk/gui/GuiMenuScreen.java | 194 ++++++++++++++++++ .../com/cjburkey/claimchunk/gui/ICCGui.java | 62 ++++++ .../claimchunk/gui/screens/MainMenu.java | 97 +++++++++ .../claimchunk/gui/screens/MapMenu.java | 123 +++++++++++ .../gui/screens/PermModifyMenu.java | 76 +++++++ .../gui/screens/PermSelectMenu.java | 54 +++++ .../claimchunk/i18n/V2JsonMessages.java | 53 +++++ .../claimchunk/service/prereq/IPrereq.java | 4 +- .../service/prereq/claim/EconPrereq.java | 48 ++--- .../service/prereq/claim/MaxChunksPrereq.java | 4 +- .../service/prereq/claim/NearChunkPrereq.java | 27 ++- .../prereq/claim/PermissionPrereq.java | 4 +- .../service/prereq/claim/PrereqClaimData.java | 38 ++-- .../service/prereq/claim/UnclaimedPrereq.java | 4 +- .../prereq/claim/WorldGuardPrereq.java | 9 +- .../service/prereq/claim/WorldPrereq.java | 7 +- .../smartcommand/sub/ply/ClaimCmd.java | 5 +- .../claimchunk/worldguard/WorldGuardApi.java | 17 +- .../worldguard/WorldGuardHandler.java | 5 +- src/main/resources/config.yml | 39 ++-- src/main/resources/plugin.yml | 2 + 29 files changed, 938 insertions(+), 112 deletions(-) create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/CCGuiHandler.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/CCOpenGui.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/GuiMenuScreen.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/ICCGui.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/screens/MainMenu.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/screens/MapMenu.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/screens/PermModifyMenu.java create mode 100644 src/main/java/com/cjburkey/claimchunk/gui/screens/PermSelectMenu.java diff --git a/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java b/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java index a7f685d0..fbe74864 100644 --- a/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java +++ b/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java @@ -12,6 +12,7 @@ import com.cjburkey.claimchunk.data.newdata.*; import com.cjburkey.claimchunk.data.sqlite.SqLiteDataHandler; import com.cjburkey.claimchunk.event.*; +import com.cjburkey.claimchunk.gui.CCGuiHandler; import com.cjburkey.claimchunk.i18n.V2JsonMessages; import com.cjburkey.claimchunk.layer.PlaceholderInitLayer; import com.cjburkey.claimchunk.layer.PrereqsInitLayer; @@ -112,6 +113,7 @@ public final class ClaimChunk extends JavaPlugin implements IClaimChunkPlugin { // The main handler (may not always be here, please don't rely on this) @Getter private MainHandler mainHandler; @Getter private ChunkOutlineHandler chunkOutlineHandler; + @Getter private CCGuiHandler guiHandler; @Getter private CCInteractClasses interactClasses; @Getter private CCPermFlags permFlags; @@ -629,10 +631,13 @@ private void setupConfig() { } private void setupEvents() { + guiHandler = new CCGuiHandler(); + // Register all the event handlers getServer().getPluginManager().registerEvents(new PlayerConnectionHandler(this), this); getServer().getPluginManager().registerEvents(new PlayerMovementHandler(this), this); getServer().getPluginManager().registerEvents(new WorldProfileEventHandler(this), this); + getServer().getPluginManager().registerEvents(guiHandler, this); } private void setupNewCommands() { diff --git a/src/main/java/com/cjburkey/claimchunk/ClaimChunkConfig.java b/src/main/java/com/cjburkey/claimchunk/ClaimChunkConfig.java index b33a28fb..2a5784e4 100644 --- a/src/main/java/com/cjburkey/claimchunk/ClaimChunkConfig.java +++ b/src/main/java/com/cjburkey/claimchunk/ClaimChunkConfig.java @@ -40,6 +40,7 @@ public class ClaimChunkConfig { @Getter private int chunkOutlineSpawnPerSec; @Getter private int chunkOutlineParticlesPerSpawn; @Getter private int chunkOutlineHeightRadius; + @Getter private boolean chunkOutlineUseNewEffect; /* Data */ @@ -75,6 +76,22 @@ public class ClaimChunkConfig { @Getter private boolean showExtraInfoOnAnonymousMetrics; @Getter private boolean debugSpam; + /* GUI */ + @Getter private String guiMenuBackButtonItem; + @Getter private String guiMainMenuCurrentChunkItem; + @Getter private String guiMainMenuChunkMapItem; + @Getter private String guiMainMenuPermFlagsItem; + @Getter private boolean guiMapMenuAllowClaimOtherChunks; + @Getter private String guiMapMenuUnclaimedItem; + @Getter private String guiMapMenuSelfClaimedItem; + @Getter private String guiMapMenuOtherClaimedItem; + @Getter private String guiMapMenuCenterUnclaimedItem; + @Getter private String guiMapMenuCenterSelfClaimedItem; + @Getter private String guiMapMenuCenterOtherClaimedItem; + @Getter private String guiPermSelectMenuItem; + @Getter private String guiPermModifyAllowItem; + @Getter private String guiPermModifyDenyItem; + /* Titles */ @Getter private boolean useTitlesInsteadOfChat; @@ -132,6 +149,7 @@ public void reload() { chunkOutlineSpawnPerSec = getInt("chunkOutline", "spawnsPerSecond"); chunkOutlineParticlesPerSpawn = getInt("chunkOutline", "particlesPerSpawn"); chunkOutlineHeightRadius = getInt("chunkOutline", "heightRadius"); + chunkOutlineUseNewEffect = getBool("chunkOutline", "useNewEffect"); keepJsonBackups = getBool("data", "keepJsonBackups"); saveDataIntervalInMinutes = getInt("data", "saveDataIntervalInMinutes"); @@ -159,6 +177,21 @@ public void reload() { showExtraInfoOnAnonymousMetrics = getBool("log", "showExtraInfoOnAnonymousMetrics"); debugSpam = getBool("log", "debugSpam"); + guiMenuBackButtonItem = getString("gui", "menuBackButtonItem"); + guiMainMenuCurrentChunkItem = getString("gui", "mainMenuCurrentChunkItem"); + guiMainMenuChunkMapItem = getString("gui", "mainMenuChunkMapItem"); + guiMainMenuPermFlagsItem = getString("gui", "mainMenuPermFlagsItem"); + guiMapMenuAllowClaimOtherChunks = getBool("gui", "mapMenuAllowClaimOtherChunks"); + guiMapMenuUnclaimedItem = getString("gui", "mapMenuUnclaimedItem"); + guiMapMenuSelfClaimedItem = getString("gui", "mapMenuSelfClaimedItem"); + guiMapMenuOtherClaimedItem = getString("gui", "mapMenuOtherClaimedItem"); + guiMapMenuCenterUnclaimedItem = getString("gui", "mapMenuCenterUnclaimedItem"); + guiMapMenuCenterSelfClaimedItem = getString("gui", "mapMenuCenterSelfClaimedItem"); + guiMapMenuCenterOtherClaimedItem = getString("gui", "mapMenuCenterOtherClaimedItem"); + guiPermSelectMenuItem = getString("gui", "permSelectMenuItem"); + guiPermModifyAllowItem = getString("gui", "permModifyAllowItem"); + guiPermModifyDenyItem = getString("gui", "permModifyDenyItem"); + useTitlesInsteadOfChat = getBool("titles", "useTitlesInsteadOfChat"); useActionBar = getBool("titles", "useActionBar"); titleFadeInTime = getInt("titles", "titleFadeInTime"); diff --git a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java index 1e2a53fe..24ed42e4 100644 --- a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java +++ b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java @@ -12,10 +12,7 @@ import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.BiFunction; /** @@ -27,6 +24,8 @@ public class CCPermFlags { public final HashMap blockControls = new HashMap<>(); public final HashMap entityControls = new HashMap<>(); + public final HashSet pvpControls = new HashSet<>(); + private final HashSet allFlags = new HashSet<>(); /** * Read the flags defined in the flag definitions file. @@ -116,6 +115,7 @@ public void loadFromConfig(@NotNull YamlConfiguration config) { Utils.err("Failed to load block flag data for flag \"%s\"", flagName); continue; } + allFlags.add(flagName); blockControls.put(flagName, blockFlagData); } case "ENTITIES" -> { @@ -136,8 +136,17 @@ public void loadFromConfig(@NotNull YamlConfiguration config) { Utils.err("Failed to load entity flag data for flag \"%s\"", flagName); continue; } + allFlags.add(flagName); entityControls.put(flagName, entityFlagData); } + case "PLAYERS" -> { + if (pvpControls.contains(flagName)) { + Utils.err("Flag \"%s\" already has pvp protection", flagName); + continue; + } + allFlags.add(flagName); + pvpControls.add(flagName); + } default -> Utils.err( "Invalid flag protection target \"%s\" for flag \"%s\"", @@ -155,6 +164,10 @@ public void loadFromConfig(@NotNull YamlConfiguration config) { } } + public @NotNull Set getAllFlags() { + return Collections.unmodifiableSet(allFlags); + } + private @Nullable YamlConfiguration readFlagFile( @NotNull File flagsFile, @NotNull JavaPlugin plugin, diff --git a/src/main/java/com/cjburkey/claimchunk/chunk/ChunkHandler.java b/src/main/java/com/cjburkey/claimchunk/chunk/ChunkHandler.java index 0ef83699..de569d85 100644 --- a/src/main/java/com/cjburkey/claimchunk/chunk/ChunkHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/chunk/ChunkHandler.java @@ -373,6 +373,16 @@ public boolean isClaimed(String world, int x, int z) { return dataHandler.isChunkClaimed(new ChunkPos(world, x, z)); } + /** + * Check if the provided chunk is claimed. + * + * @param pos The position of the chunk + * @return Whether this chunk is currently claimed. + */ + public boolean isClaimed(ChunkPos pos) { + return dataHandler.isChunkClaimed(pos); + } + /** * Check if the provided chunk is claimed. * diff --git a/src/main/java/com/cjburkey/claimchunk/cmd/MainHandler.java b/src/main/java/com/cjburkey/claimchunk/cmd/MainHandler.java index b7d2ddb1..af207c30 100644 --- a/src/main/java/com/cjburkey/claimchunk/cmd/MainHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/cmd/MainHandler.java @@ -118,7 +118,7 @@ public void outlineChunk(ChunkPos chunk, Player showTo, int timeToShow) { } } - public void claimChunk(Player p, Chunk loc) { + public void claimChunk(Player p, ChunkPos loc) { final ChunkHandler chunkHandler = claimChunk.getChunkHandler(); claimChunk @@ -135,20 +135,14 @@ public void claimChunk(Player p, Chunk loc) { // Claim the chunk if nothing is wrong ChunkPos pos = chunkHandler.claimChunk( - loc.getWorld(), - loc.getX(), - loc.getZ(), - p.getUniqueId()); + loc.world(), loc.x(), loc.z(), p.getUniqueId()); // Error check, though it *shouldn't* occur if (pos == null) { Utils.err( "Failed to claim chunk (%s, %s) in world %s for player %s." + " The data handler returned a null position?", - loc.getX(), - loc.getZ(), - loc.getWorld().getName(), - p.getName()); + loc.x(), loc.z(), loc.world(), p.getName()); return; } diff --git a/src/main/java/com/cjburkey/claimchunk/event/PlayerMovementHandler.java b/src/main/java/com/cjburkey/claimchunk/event/PlayerMovementHandler.java index 72e3e55f..29d9e6cb 100644 --- a/src/main/java/com/cjburkey/claimchunk/event/PlayerMovementHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/event/PlayerMovementHandler.java @@ -4,6 +4,7 @@ import com.cjburkey.claimchunk.Utils; import com.cjburkey.claimchunk.chunk.AutoClaimHandler; import com.cjburkey.claimchunk.chunk.ChunkHandler; +import com.cjburkey.claimchunk.chunk.ChunkPos; import com.cjburkey.claimchunk.player.PlayerHandler; import org.bukkit.Bukkit; @@ -39,7 +40,7 @@ public void onPlayerMove(PlayerMoveEvent e) { if (prev.getX() != to.getX() || prev.getZ() != to.getZ()) { // If the claim is currently auto-claiming, try to claim this chunk if (AutoClaimHandler.inList(e.getPlayer())) { - claimChunk.getMainHandler().claimChunk(e.getPlayer(), to); + claimChunk.getMainHandler().claimChunk(e.getPlayer(), new ChunkPos(to)); return; } diff --git a/src/main/java/com/cjburkey/claimchunk/gui/CCGuiHandler.java b/src/main/java/com/cjburkey/claimchunk/gui/CCGuiHandler.java new file mode 100644 index 00000000..2ed07db1 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/CCGuiHandler.java @@ -0,0 +1,89 @@ +package com.cjburkey.claimchunk.gui; + +import com.cjburkey.claimchunk.Utils; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.UUID; + +/** + * The handler behind ClaimChunk GUI screens. This class acts as the interface for opening GUIs as + * well as the event listener for players clicking in/closing the screens. + * + * @since 0.0.26 + */ +public class CCGuiHandler implements Listener { + + private final HashMap openGuis = new HashMap<>(); + + @EventHandler + public void onGuiClick(InventoryClickEvent e) { + UUID uuid = e.getWhoClicked().getUniqueId(); + CCOpenGui openGui = openGuis.get(uuid); + if (openGui != null) { + if (e.getInventory().equals(openGui.inventory()) + && e.getSlot() >= 0 + && e.getSlot() < e.getInventory().getSize()) { + openGui.gui() + .onClick( + openGui.inventory(), e.getSlot(), e.getClick(), e.getCurrentItem()); + } + e.setCancelled(true); + } + } + + @EventHandler + public void onGuiClose(InventoryCloseEvent e) { + if (openGuis.containsKey(e.getPlayer().getUniqueId())) { + closeGui((Player) e.getPlayer()); + } + } + + public void openOrRefreshGui(@NotNull ICCGui gui) { + Player player = gui.getPlayer(); + CCOpenGui openGui = closeGui(player, false); + + final Inventory inventory; + if (openGui != null && openGui.gui() == gui) { + inventory = openGui.inventory(); + inventory.clear(); + } else { + inventory = createAndShowGui(player, gui); + } + + openGuis.put(player.getUniqueId(), new CCOpenGui(gui, inventory)); + gui.onOpen(openGuis.get(player.getUniqueId()).inventory()); + } + + public void closeGui(@NotNull Player player) { + closeGui(player, true); + } + + private @Nullable CCOpenGui closeGui(@NotNull Player player, boolean removeFromMap) { + CCOpenGui openGui = openGuis.get(player.getUniqueId()); + if (openGui != null) { + openGui.gui().onClose(openGuis.get(player.getUniqueId()).inventory()); + if (removeFromMap) { + openGuis.remove(player.getUniqueId()); + } + } + return openGui; + } + + private static Inventory createAndShowGui(@NotNull Player player, @NotNull ICCGui gui) { + int rowCount = Math.min(Math.max(gui.getRows(), 1), 6); + Inventory inventory = + Bukkit.createInventory(player, rowCount * 9, Utils.color(gui.getName())); + player.openInventory(inventory); + return inventory; + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/CCOpenGui.java b/src/main/java/com/cjburkey/claimchunk/gui/CCOpenGui.java new file mode 100644 index 00000000..6de89b18 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/CCOpenGui.java @@ -0,0 +1,5 @@ +package com.cjburkey.claimchunk.gui; + +import org.bukkit.inventory.Inventory; + +record CCOpenGui(ICCGui gui, Inventory inventory) {} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/GuiMenuScreen.java b/src/main/java/com/cjburkey/claimchunk/gui/GuiMenuScreen.java new file mode 100644 index 00000000..0a146fc5 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/GuiMenuScreen.java @@ -0,0 +1,194 @@ +package com.cjburkey.claimchunk.gui; + +import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.Utils; +import com.cjburkey.claimchunk.chunk.ChunkPos; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; + +/** + * An abstract wrapper for {@link ICCGui} to make creating inventory menus easier. + * + * @since 0.0.26 + */ +public abstract class GuiMenuScreen implements ICCGui { + + /** Anonymous callback for item click event. */ + @FunctionalInterface + public interface GuiItemAction { + /** Called when the item is clicked. */ + void onClick(@NotNull ClickType clickType, @NotNull ItemStack stack); + } + + /** Wrapper around an interactive item in the GUI menu. */ + record GuiItemWrapper(@NotNull ItemStack stack, @NotNull GuiItemAction action) {} + + protected final ClaimChunk claimChunk; + private final Player player; + private final int rowCount; + private final String name; + private final GuiItemWrapper[] actions; + + protected GuiMenuScreen( + ClaimChunk claimChunk, @NotNull Player player, int rowCount, @NotNull String name) { + this.claimChunk = claimChunk; + this.player = player; + this.rowCount = Math.min(Math.max(rowCount, 1), 6); + this.name = name; + this.actions = new GuiItemWrapper[this.rowCount * 9]; + } + + /** + * Add an interactive button item to this inventory GUI. + * + * @param inventory This GUI's inventory. + * @param slot The slot of the inventory in which to put the item. + * @param itemType The material of the item. + * @param itemName The display name of the item stack. + * @param itemLore The lore attached to the item. + * @param action The on-click callback + */ + protected void addInteractiveButton( + @NotNull Inventory inventory, + int slot, + @NotNull Material itemType, + @NotNull String itemName, + @NotNull List itemLore, + @NotNull GuiItemAction action) { + if (slot >= 0 && slot < this.actions.length && itemType != Material.AIR) { + ItemStack stack = makeStack(itemType, itemName, itemLore); + if (stack != null) { + inventory.setItem(slot, stack); + this.actions[slot] = new GuiItemWrapper(stack, action); + } + } + } + + private @Nullable ItemStack makeStack( + @NotNull Material itemType, @NotNull String itemName, @NotNull List itemLore) { + ItemStack stack = new ItemStack(itemType); + ItemMeta meta = stack.getItemMeta(); + if (meta == null) return null; + meta.setDisplayName(Utils.color(itemName)); + meta.setLore(itemLore.stream().map(Utils::color).toList()); + stack.setItemMeta(meta); + return stack; + } + + /** Method to reopen this gui (to update item names, etc.) */ + protected void refresh() { + claimChunk.getGuiHandler().openOrRefreshGui(this); + } + + @Override + public void onClick( + @NotNull Inventory inventory, + int slot, + @NotNull ClickType clickType, + @Nullable ItemStack stack) { + assert slot >= 0 && slot < actions.length; + + GuiItemWrapper action = actions[slot]; + if (action != null && stack != null) { + action.action().onClick(clickType, stack); + } + } + + @Override + public void onClose(@NotNull Inventory inventory) {} + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public int getRows() { + return rowCount; + } + + @Override + public Player getPlayer() { + return player; + } + + /** + * Get the given item name's associated {@link Material} enum variant. + * + * @param val The item name, like {@code minecraft:grass_block}. + * @return The Material, or {@link Material#BARRIER} if the provided item isn't valid. + */ + protected static @NotNull Material materialFromStr(String val) { + Material item = Material.matchMaterial(val); + if (item == null) { + item = Material.BARRIER; + } + return item; + } + + /** + * Generate chunk position text based on the message handler. + * + * @param chunkPos The position of the chunk + * @return A localized string representing a position in the given world. + */ + protected @NotNull String guiChunkPosText(@NotNull ChunkPos chunkPos) { + return claimChunk + .getMessages() + .guiChunkPos + .replaceAll(Pattern.quote("%%WORLD%%"), chunkPos.world()) + .replaceAll(Pattern.quote("%%X%%"), chunkPos.x() + "") + .replaceAll(Pattern.quote("%%Z%%"), chunkPos.z() + ""); + } + + /** + * Helper method to generate localized chunk owner name GUI text. + * + * @param chunkName The non-null name of the chunk owner. This replaces {@code %%NAME%%} + * verbatim. + * @return Player-facing localized chunk owner text. + */ + protected @NotNull String guiChunkOwnerNameText(@NotNull String chunkName) { + return claimChunk + .getMessages() + .guiChunkOwner + .replaceAll(Pattern.quote("%%NAME%%"), chunkName); + } + + /** + * Helper method to get the name for this given chunk owner, or return the localized unknown + * player text. + * + * @param chunkOwner The non-null owner of the chunk. + * @return The name for the chunk's owner that can be shown to a player in the GUI. + */ + protected @NotNull String chunkNameOrUnknown(@NotNull UUID chunkOwner) { + String chunkName = claimChunk.getPlayerHandler().getChunkName(chunkOwner); + return chunkName != null ? chunkName : claimChunk.getMessages().unknownChunkOwner; + } + + protected static @NotNull List splitLineLore(@NotNull String loreLine) { + return Arrays.asList(loreLine.split("\n")); + } + + /** + * Helper method to open the given GUI for its respective player. + * + * @param gui The gui to open. + */ + protected void openGui(@NotNull ICCGui gui) { + claimChunk.getGuiHandler().openOrRefreshGui(gui); + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/ICCGui.java b/src/main/java/com/cjburkey/claimchunk/gui/ICCGui.java new file mode 100644 index 00000000..05858f73 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/ICCGui.java @@ -0,0 +1,62 @@ +package com.cjburkey.claimchunk.gui; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Interface representing a ClaimChunk GUI screen. + * + * @since 0.0.26 + */ +public interface ICCGui { + + /** + * Called when the GUI is being constructed to be shown to the player. + * + *

Modify the inventory inside this method + * + * @param inventory The inventory being shown. + */ + void onOpen(@NotNull Inventory inventory); + + /** + * Called when the GUI is closed; nothing usually needs to happen, but just in case, you know? + * + * @param inventory The inventory being shown. + */ + void onClose(@NotNull Inventory inventory); + + /** + * Called when the player clicks on a given slot within the inventory. + * + * @param inventory The inventory being shown. + * @param slot The index of the slot being clicked. + * @param clickType Which type of click the player performed. + * @param stack The stack on which the player clicked. + */ + void onClick( + @NotNull Inventory inventory, + int slot, + @NotNull ClickType clickType, + @Nullable ItemStack stack); + + /** + * @return The name to be shown at the top of the GUI + */ + @NotNull + String getName(); + + /** + * @return The number of rows this GUI should have + */ + int getRows(); + + /** + * @return The player this GUI is going to be shown to. + */ + Player getPlayer(); +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/screens/MainMenu.java b/src/main/java/com/cjburkey/claimchunk/gui/screens/MainMenu.java new file mode 100644 index 00000000..890483af --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/screens/MainMenu.java @@ -0,0 +1,97 @@ +package com.cjburkey.claimchunk.gui.screens; + +import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.chunk.ChunkPos; +import com.cjburkey.claimchunk.gui.GuiMenuScreen; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.UUID; + +public class MainMenu extends GuiMenuScreen { + + // +---------+ + // |XX2X4X6XX| + // +---------+ + // 2: Current chunk info + // 4: Chunk map + // 6: Chunk permissions + + public MainMenu(ClaimChunk claimChunk, Player player) { + super(claimChunk, player, 1, claimChunk.getMessages().guiMainMenuTitle); + } + + @Override + public void onOpen(@NotNull Inventory inventory) { + addCurrentChunkItem(inventory); + addMapItem(inventory); + addPermsItem(inventory); + } + + private void addCurrentChunkItem(@NotNull Inventory inventory) { + ChunkPos chunkPos = new ChunkPos(getPlayer().getLocation().getChunk()); + UUID chunkOwner = claimChunk.getChunkHandler().getOwner(chunkPos); + + ArrayList lore = new ArrayList<>(); + + lore.add(guiChunkPosText(chunkPos)); + if (chunkOwner != null) { + lore.add(guiChunkOwnerNameText(chunkNameOrUnknown(chunkOwner))); + if (chunkOwner.equals(getPlayer().getUniqueId())) { + lore.add(""); + lore.add(claimChunk.getMessages().guiClickToUnclaim); + } + } else { + lore.add(claimChunk.getMessages().guiNotClaimed); + lore.add(""); + lore.add(claimChunk.getMessages().guiClickToClaim); + } + + addInteractiveButton( + inventory, + 2, + materialFromStr(claimChunk.getConfigHandler().getGuiMainMenuCurrentChunkItem()), + claimChunk.getMessages().guiMainMenuCurrentChunkItemName, + lore, + (clickType, stack) -> { + if (clickType.isLeftClick()) { + claimChunk.getMainHandler().claimChunk(getPlayer(), chunkPos); + refresh(); + } else if (clickType.isRightClick()) { + claimChunk + .getMainHandler() + .unclaimChunk( + false, + false, + getPlayer(), + chunkPos.world(), + chunkPos.x(), + chunkPos.z()); + refresh(); + } + }); + } + + private void addMapItem(@NotNull Inventory inventory) { + addInteractiveButton( + inventory, + 4, + materialFromStr(claimChunk.getConfigHandler().getGuiMainMenuChunkMapItem()), + claimChunk.getMessages().guiMainMenuMapItemName, + splitLineLore(claimChunk.getMessages().guiMainMenuMapItemDesc), + (clickType, stack) -> openGui(new MapMenu(claimChunk, getPlayer()))); + } + + private void addPermsItem(@NotNull Inventory inventory) { + addInteractiveButton( + inventory, + 6, + materialFromStr(claimChunk.getConfigHandler().getGuiMainMenuPermFlagsItem()), + claimChunk.getMessages().guiMainMenuPermFlagsItemName, + splitLineLore(claimChunk.getMessages().guiMainMenuPermFlagsDescription), + (clickType, stack) -> openGui(new PermSelectMenu(claimChunk, getPlayer()))); + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/screens/MapMenu.java b/src/main/java/com/cjburkey/claimchunk/gui/screens/MapMenu.java new file mode 100644 index 00000000..4381c214 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/screens/MapMenu.java @@ -0,0 +1,123 @@ +package com.cjburkey.claimchunk.gui.screens; + +import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.ClaimChunkConfig; +import com.cjburkey.claimchunk.chunk.ChunkHandler; +import com.cjburkey.claimchunk.chunk.ChunkPos; +import com.cjburkey.claimchunk.gui.GuiMenuScreen; +import com.cjburkey.claimchunk.i18n.V2JsonMessages; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.UUID; + +public class MapMenu extends GuiMenuScreen { + + private static final int MAP_HEIGHT = 5; + + public MapMenu(@NotNull ClaimChunk claimChunk, @NotNull Player player) { + // Offset to make it 6 tall so that we can have the top row be a menu bar. + super(claimChunk, player, MAP_HEIGHT + 1, claimChunk.getMessages().guiMapMenuTitle); + } + + @Override + public void onOpen(@NotNull Inventory inventory) { + int halfHeight = Math.floorDiv(MAP_HEIGHT, 2); + + ChunkHandler chunkHandler = claimChunk.getChunkHandler(); + V2JsonMessages messages = claimChunk.getMessages(); + ClaimChunkConfig config = claimChunk.getConfigHandler(); + ChunkPos centerChunk = new ChunkPos(getPlayer().getLocation().getChunk()); + boolean enableClaimingFromMap = config.getGuiMapMenuAllowClaimOtherChunks(); + + // Add the back button + addInteractiveButton( + inventory, + 0, + materialFromStr(config.getGuiMenuBackButtonItem()), + messages.guiMenuBackButtonName, + Collections.singletonList(messages.guiMenuBackButtonDesc), + (clickType, stack) -> openGui(new MainMenu(claimChunk, getPlayer()))); + + // Add the map items + // Inventory width is 9, so go 4 eastward and westward + for (int offsetX = -4; offsetX <= 4; offsetX++) { + // Inventory height is `MAP_HEIGHT`, so go `halfHeight` northward and southward + for (int offsetZ = -halfHeight; offsetZ <= halfHeight; offsetZ++) { + // The `+1` pushes down by one row, for the top row menu bar idea I have. + int slot = (offsetX + 4) + 9 * (offsetZ + halfHeight + 1); + ChunkPos offsetChunk = + new ChunkPos( + centerChunk.world(), + centerChunk.x() + offsetX, + centerChunk.z() + offsetZ); + boolean isCenter = offsetChunk.equals(centerChunk); + + ArrayList lore = new ArrayList<>(); + UUID chunkOwner = chunkHandler.getOwner(offsetChunk); + boolean isOwner = getPlayer().getUniqueId().equals(chunkOwner); + + if (isCenter) lore.add(messages.guiMapMenuInsideThisChunk); + + if (chunkOwner != null) { + lore.add(guiChunkOwnerNameText(chunkNameOrUnknown(chunkOwner))); + if (enableClaimingFromMap && isOwner) { + lore.add(""); + lore.add(messages.guiClickToUnclaim); + } + } else { + lore.add(messages.guiNotClaimed); + if (enableClaimingFromMap) { + lore.add(""); + lore.add(messages.guiClickToClaim); + } + } + + String mapItemMaterialStr; + if (isCenter) { + mapItemMaterialStr = + isOwner + ? config.getGuiMapMenuCenterSelfClaimedItem() + : chunkOwner == null + ? config.getGuiMapMenuCenterUnclaimedItem() + : config.getGuiMapMenuCenterOtherClaimedItem(); + } else { + mapItemMaterialStr = + isOwner + ? config.getGuiMapMenuSelfClaimedItem() + : chunkOwner == null + ? config.getGuiMapMenuUnclaimedItem() + : config.getGuiMapMenuOtherClaimedItem(); + } + + addInteractiveButton( + inventory, + slot, + materialFromStr(mapItemMaterialStr), + guiChunkPosText(offsetChunk), + lore, + (clickType, stack) -> { + if (clickType.isLeftClick()) { + // claimChunk.getMainHandler().claimChunk(getPlayer(), offsetChunk); + refresh(); + } else if (clickType.isRightClick()) { + claimChunk + .getMainHandler() + .unclaimChunk( + false, + false, + getPlayer(), + offsetChunk.world(), + offsetChunk.x(), + offsetChunk.z()); + refresh(); + } + }); + } + } + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/screens/PermModifyMenu.java b/src/main/java/com/cjburkey/claimchunk/gui/screens/PermModifyMenu.java new file mode 100644 index 00000000..08a72591 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/screens/PermModifyMenu.java @@ -0,0 +1,76 @@ +package com.cjburkey.claimchunk.gui.screens; + +import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.ClaimChunkConfig; +import com.cjburkey.claimchunk.gui.GuiMenuScreen; +import com.cjburkey.claimchunk.i18n.V2JsonMessages; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +public class PermModifyMenu extends GuiMenuScreen { + + public final boolean isAllChunks; + public final boolean isAllPlayers; + + public PermModifyMenu( + @NotNull ClaimChunk claimChunk, + @NotNull Player player, + boolean isAllChunks, + boolean isAllPlayers) { + // Offset to make it 6 tall so that we can have the top row be a menu bar. + super(claimChunk, player, 4, claimChunk.getMessages().guiPermSelectMenuTitle); + + this.isAllChunks = isAllChunks; + this.isAllPlayers = isAllPlayers; + } + + @Override + public void onOpen(@NotNull Inventory inventory) { + V2JsonMessages messages = claimChunk.getMessages(); + ClaimChunkConfig config = claimChunk.getConfigHandler(); + Material allowItem = materialFromStr(config.getGuiPermSelectMenuItem()); + Material denyItem = materialFromStr(config.getGuiPermSelectMenuItem()); + + // Back button + addInteractiveButton( + inventory, + 0, + materialFromStr(config.getGuiMenuBackButtonItem()), + messages.guiMenuBackButtonName, + splitLineLore(messages.guiMenuBackButtonDesc), + (clickType, stack) -> openGui(new PermSelectMenu(claimChunk, getPlayer()))); + + // Add permission buttons + // TODO: THIS! + Map permissions = + claimChunk.getPermFlags().getAllFlags().stream() + .collect( + HashMap::new, (acc, flag) -> acc.put(flag, false), HashMap::putAll); + + int slot = 0; + for (Map.Entry permission : permissions.entrySet()) { + addInteractiveButton( + inventory, + 9 + slot, + permission.getValue() ? allowItem : denyItem, + "&r&f" + permission.getKey(), + splitLineLore(messages.guiPermModifyPermDesc), + (clickType, stack) -> {}); + slot++; + } + } + + @Override + public @NotNull String getName() { + V2JsonMessages messages = claimChunk.getMessages(); + return isAllChunks + ? messages.guiPermModifyAllMenuTitle + : messages.guiPermModifyThisMenuTitle; + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/gui/screens/PermSelectMenu.java b/src/main/java/com/cjburkey/claimchunk/gui/screens/PermSelectMenu.java new file mode 100644 index 00000000..0c69d4b7 --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/gui/screens/PermSelectMenu.java @@ -0,0 +1,54 @@ +package com.cjburkey.claimchunk.gui.screens; + +import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.ClaimChunkConfig; +import com.cjburkey.claimchunk.gui.GuiMenuScreen; +import com.cjburkey.claimchunk.i18n.V2JsonMessages; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +public class PermSelectMenu extends GuiMenuScreen { + + public PermSelectMenu(@NotNull ClaimChunk claimChunk, @NotNull Player player) { + // Offset to make it 6 tall so that we can have the top row be a menu bar. + super(claimChunk, player, 1, claimChunk.getMessages().guiPermSelectMenuTitle); + } + + @Override + public void onOpen(@NotNull Inventory inventory) { + V2JsonMessages messages = claimChunk.getMessages(); + ClaimChunkConfig config = claimChunk.getConfigHandler(); + + // Back button + addInteractiveButton( + inventory, + 0, + materialFromStr(config.getGuiMenuBackButtonItem()), + messages.guiMenuBackButtonName, + splitLineLore(messages.guiPermModifyBackButtonDesc), + (clickType, stack) -> openGui(new MainMenu(claimChunk, getPlayer()))); + + Material item = materialFromStr(config.getGuiPermSelectMenuItem()); + + // Permission type selection button + addInteractiveButton( + inventory, + 4, + item, + messages.guiPermSelectMenuThisChunkName, + splitLineLore(messages.guiPermSelectMenuThisChunkDesc), + (clickType, stack) -> + openGui(new PermModifyMenu(claimChunk, getPlayer(), false, true))); + addInteractiveButton( + inventory, + 5, + item, + messages.guiPermSelectMenuAllChunksName, + splitLineLore(messages.guiPermSelectMenuAllChunksDesc), + (clickType, stack) -> + openGui(new PermModifyMenu(claimChunk, getPlayer(), true, true))); + } +} diff --git a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java index deff9360..3b8c6185 100644 --- a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java +++ b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java @@ -181,6 +181,59 @@ public final class V2JsonMessages { "&cYou can't place &e%%BLOCK%%&c in unclaimed chunks"; public String chunkCancelPearlLaunch = "&cYou can't use ender pearls in &e%%OWNER%%&c's chunk"; + // GUI localization + // General + public String guiChunkPos = "&fIn &e%%WORLD%%&f at (&e%%X%%&f, &e%%Z%%&f)"; + public String guiChunkOwner = "&fOwner: %%NAME%%"; + public String guiNotClaimed = "&fNot claimed"; + public String guiClickToClaim = "&2Left click to claim!"; + public String guiClickToUnclaim = "&4Right click to unclaim"; + public String guiMenuBackButtonName = "&r&3&lBack"; + public String guiMenuBackButtonDesc = "&r&fReturn to the main menu"; + // Main menu + public String guiMainMenuTitle = "ClaimChunk Main GUI"; + public String guiMainMenuCurrentChunkItemName = "&r&3&lCurrent Chunk"; + public String guiMainMenuMapItemName = "&r&3&lChunk Map"; + public String guiMainMenuMapItemDesc = "&r&fClick to view the in-game map"; + public String guiMainMenuPermFlagsItemName = "&r&3&lPermission Flags"; + public String guiMainMenuPermFlagsDescription = + """ + &r&fClick to manage other players' + &r&fpermissions in your chunk(s) + """; + // Map menu + public String guiMapMenuTitle = "ClaimChunk Map"; + public String guiMapMenuInsideThisChunk = "&r&fYou are standing inside this chunk"; + // Permission type selection menu + public String guiPermSelectMenuTitle = "Chunk Permissions Selection"; + public String guiPermSelectMenuThisChunkName = "&r&3&lPlayers in This Chunk"; + public String guiPermSelectMenuThisChunkDesc = + """ + &r&fModify permissions that other + &r&fplayers have in this chunk + """; + public String guiPermSelectMenuAllChunksName = "&r&3&lPlayers in All Chunks"; + public String guiPermSelectMenuAllChunksDesc = + """ + &r&fModify permissions that other + &r&fplayers have in all chunks + &r&facross all dimensions + """; + // TODO: SPECIFIC PLAYER PERM ITEMS + // Modify permissions screen + public String guiPermModifyAllMenuTitle = "Modify All Chunks"; + public String guiPermModifyThisMenuTitle = "Modify This Chunk"; + public String guiPermModifyBackButtonDesc = + """ + &r&fReturn to the permission type + &r&fselection screen + """; + public String guiPermModifyPermDesc = + """ + &r&eLeft click&f to &aAllow + &r&eRight click&f to &cDeny + """; + // AdminOverride localization public String adminOverrideEnable = "&eYou now have protection bypass"; public String adminOverrideDisable = "&eYou no longer have protection bypass"; diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/IPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/IPrereq.java index a04bfb9e..e6568845 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/IPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/IPrereq.java @@ -22,8 +22,8 @@ public interface IPrereq { /** * Determines whether the provided player should be able to perform the action. Note: this * method should not change the state of anything as it's currently unknown whether the action - * could fail after this check. If a subsequent check fails, then the action doesn't not occur, - * so it's important to make sure nothing is changed in this method. + * could fail after this check. If a subsequent check fails, then the action does not occur, so + * it's important to make sure nothing is changed in this method. * * @param data The prerequisite data. * @return Whether this prerequisite was met. diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/EconPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/EconPrereq.java index 1ad40499..d19142a3 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/EconPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/EconPrereq.java @@ -15,12 +15,12 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - if (data.claimChunk.useEconomy() - && data.claimChunk.getChunkHandler().getHasAllFreeChunks(data.playerId)) { - double cost = data.claimChunk.getConfigHandler().getClaimPrice(); + if (data.claimChunk().useEconomy() + && data.claimChunk().getChunkHandler().getHasAllFreeChunks(data.playerId())) { + double cost = data.claimChunk().getConfigHandler().getClaimPrice(); // Check if the chunk is free or the player has enough money - return cost <= 0 || data.claimChunk.getEconomy().getMoney(data.playerId) >= cost; + return cost <= 0 || data.claimChunk().getEconomy().getMoney(data.playerId()) >= cost; } return true; } @@ -32,50 +32,50 @@ public Optional getErrorMessage(@NotNull PrereqClaimData data) { // chunk is larger than $0.00, and the player cannot afford the cost of // the chunk claiming. Therefore, this is the only error that is // possible - return Optional.of(data.claimChunk.getMessages().claimNotEnoughMoney); + return Optional.of(data.claimChunk().getMessages().claimNotEnoughMoney); } @Override public Optional getSuccessMessage(@NotNull PrereqClaimData data) { // Check if the economy isn't being used, in which case it's not the // responsibility of this prereq to set the success message - if (!data.claimChunk.useEconomy()) { + if (!data.claimChunk().useEconomy()) { return Optional.empty(); } // Check if the player should get this chunk for free because they // haven't claimed all of their free chunks yet // If the chunk is free, determine the message to display based on how many chunks are free - if (!data.claimChunk + if (!data.claimChunk() .getChunkHandler() - .getHasAllFreeChunks(data.playerId, data.freeClaims)) { - if (data.freeClaims <= 1) { + .getHasAllFreeChunks(data.playerId(), data.freeClaims())) { + if (data.freeClaims() <= 1) { // Only one free chunk (or error?) // We shouldn't get this far if players can't claim free chunks - return Optional.of(data.claimChunk.getMessages().claimFree1); + return Optional.of(data.claimChunk().getMessages().claimFree1); } // Multiple free chunks return Optional.of( - data.claimChunk + data.claimChunk() .getMessages() .claimFrees - .replace("%%COUNT%%", data.freeClaims + "")); + .replace("%%COUNT%%", data.freeClaims() + "")); } else { - double cost = data.claimChunk.getConfigHandler().getClaimPrice(); + double cost = data.claimChunk().getConfigHandler().getClaimPrice(); // The success message includes the price // If the price is less than or 0 (free), then it should display // that it's free return Optional.of( - data.claimChunk + data.claimChunk() .getMessages() .claimSuccess .replace( "%%PRICE%%", (cost <= 0.0d) - ? data.claimChunk.getMessages().claimNoCost - : data.claimChunk.getEconomy().format(cost))); + ? data.claimChunk().getMessages().claimNoCost + : data.claimChunk().getEconomy().format(cost))); } } @@ -84,22 +84,22 @@ public Optional getSuccessMessage(@NotNull PrereqClaimData data) { // (obviously) @Override public void onSuccess(@NotNull PrereqClaimData data) { - if (data.claimChunk.useEconomy()) { - if (data.claimedBefore < data.freeClaims) { + if (data.claimChunk().useEconomy()) { + if (data.claimedBefore() < data.freeClaims()) { // This chunk is free! return; } - double cost = data.claimChunk.getConfigHandler().getClaimPrice(); + double cost = data.claimChunk().getConfigHandler().getClaimPrice(); - if (!data.claimChunk.getEconomy().buy(data.playerId, cost)) { + if (!data.claimChunk().getEconomy().buy(data.playerId(), cost)) { // Error check Utils.err( "Failed to buy chunk (%s, %s) in world %s for player %s", - data.chunk.getX(), - data.chunk.getZ(), - data.chunk.getWorld().getName(), - data.player != null ? data.player.getName() : data.playerId); + data.chunk().x(), + data.chunk().z(), + data.chunk().world(), + data.player() != null ? data.player().getName() : data.playerId()); } } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/MaxChunksPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/MaxChunksPrereq.java index d6da3701..c25dddc8 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/MaxChunksPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/MaxChunksPrereq.java @@ -13,11 +13,11 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - return !(data.maxClaimed > 0 && data.claimedBefore >= data.maxClaimed); + return !(data.maxClaimed() > 0 && data.claimedBefore() >= data.maxClaimed()); } @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().claimTooMany); + return Optional.of(data.claimChunk().getMessages().claimTooMany); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/NearChunkPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/NearChunkPrereq.java index d784f1b6..a0eabd2b 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/NearChunkPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/NearChunkPrereq.java @@ -1,12 +1,14 @@ package com.cjburkey.claimchunk.service.prereq.claim; import org.bukkit.Chunk; +import org.bukkit.World; import org.jetbrains.annotations.NotNull; import java.util.Optional; import java.util.UUID; public class NearChunkPrereq implements IClaimPrereq { + @Override public int getWeight() { return 300; @@ -17,28 +19,31 @@ public boolean getPassed(@NotNull PrereqClaimData data) { boolean nearClaimed = false; // Get the diameter around the player to check - int near = data.claimChunk.getConfigHandler().getNearChunkSearch(); + int near = data.claimChunk().getConfigHandler().getNearChunkSearch(); if (near < 1) return true; // Get starting and ending bounds int min = (near - 1) / 2; int max = (near - 1) / 2 + 1; + World world = data.claimChunk().getServer().getWorld(data.chunk().world()); + if (world == null) { + return false; + } + // Check through chunks within the given area for (int x1 = -min; x1 < max; x1++) { for (int z1 = -min; z1 < max; z1++) { - if (nearClaimed || data.player.hasPermission("claimchunk.bypassnearbychunk")) break; + if (nearClaimed || data.player().hasPermission("claimchunk.bypassnearbychunk")) + break; - Chunk chunk = - data.chunk - .getWorld() - .getChunkAt(x1 + data.chunk.getX(), z1 + data.chunk.getZ()); + Chunk chunk = world.getChunkAt(x1 + data.chunk().x(), z1 + data.chunk().z()); - if (data.claimChunk.getChunkHandler().isOwner(chunk, data.player)) continue; - nearClaimed = data.claimChunk.getChunkHandler().isClaimed(chunk); - UUID owner = data.claimChunk.getChunkHandler().getOwner(data.chunk); + if (data.claimChunk().getChunkHandler().isOwner(chunk, data.player())) continue; + nearClaimed = data.claimChunk().getChunkHandler().isClaimed(chunk); + UUID owner = data.claimChunk().getChunkHandler().getOwner(data.chunk()); // If the given chunk is owned but not by this player, fail this prereq - if (owner != null && owner.equals(data.playerId)) return false; + if (owner != null && owner.equals(data.playerId())) return false; } } @@ -48,6 +53,6 @@ public boolean getPassed(@NotNull PrereqClaimData data) { @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().nearChunkSearch); + return Optional.of(data.claimChunk().getMessages().nearChunkSearch); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PermissionPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PermissionPrereq.java index 165e3276..41c3cea1 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PermissionPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PermissionPrereq.java @@ -16,11 +16,11 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - return Utils.hasPerm(data.player, true, "claim"); + return Utils.hasPerm(data.player(), true, "claim"); } @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().claimNoPerm); + return Optional.of(data.claimChunk().getMessages().claimNoPerm); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PrereqClaimData.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PrereqClaimData.java index 4abffbcf..3c1bfca4 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PrereqClaimData.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/PrereqClaimData.java @@ -1,37 +1,35 @@ package com.cjburkey.claimchunk.service.prereq.claim; import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.chunk.ChunkPos; -import org.bukkit.Chunk; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.UUID; -public final class PrereqClaimData { - - public final ClaimChunk claimChunk; - public final Chunk chunk; - public final UUID playerId; - public final Player player; - // Automatically loaded - public final int claimedBefore; - public final int maxClaimed; - public final int freeClaims; +public record PrereqClaimData( + ClaimChunk claimChunk, + ChunkPos chunk, + UUID playerId, + Player player, + int claimedBefore, + int maxClaimed, + int freeClaims) { public PrereqClaimData( @NotNull ClaimChunk claimChunk, - @NotNull Chunk chunk, + @NotNull ChunkPos chunk, @NotNull UUID playerId, @Nullable Player player) { - this.claimChunk = claimChunk; - this.chunk = chunk; - this.playerId = playerId; - this.player = player; - - this.claimedBefore = claimChunk.getChunkHandler().getClaimed(playerId); - this.maxClaimed = claimChunk.getRankHandler().getMaxClaimsForPlayer(player); - this.freeClaims = claimChunk.getConfigHandler().getFirstFreeChunks(); + this( + claimChunk, + chunk, + playerId, + player, + claimChunk.getChunkHandler().getClaimed(playerId), + claimChunk.getRankHandler().getMaxClaimsForPlayer(player), + claimChunk.getConfigHandler().getFirstFreeChunks()); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/UnclaimedPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/UnclaimedPrereq.java index a965cba7..5a4b3d22 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/UnclaimedPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/UnclaimedPrereq.java @@ -13,11 +13,11 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - return !data.claimChunk.getChunkHandler().isClaimed(data.chunk); + return !data.claimChunk().getChunkHandler().isClaimed(data.chunk()); } @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().claimAlreadyOwned); + return Optional.of(data.claimChunk().getMessages().claimAlreadyOwned); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldGuardPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldGuardPrereq.java index 3ab442d8..51d9b983 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldGuardPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldGuardPrereq.java @@ -16,15 +16,16 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - boolean allowedToClaimWG = WorldGuardHandler.isAllowedClaim(data.claimChunk, data.chunk); - boolean adminOverride = data.claimChunk.getConfigHandler().getAllowWGAdminOverride(); - boolean hasAdmin = Utils.hasAdmin(data.player); + boolean allowedToClaimWG = + WorldGuardHandler.isAllowedClaim(data.claimChunk(), data.chunk()); + boolean adminOverride = data.claimChunk().getConfigHandler().getAllowWGAdminOverride(); + boolean hasAdmin = Utils.hasAdmin(data.player()); return allowedToClaimWG || (adminOverride && hasAdmin); } @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().claimLocationBlock); + return Optional.of(data.claimChunk().getMessages().claimLocationBlock); } } diff --git a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldPrereq.java b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldPrereq.java index a0a50fef..59257336 100644 --- a/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldPrereq.java +++ b/src/main/java/com/cjburkey/claimchunk/service/prereq/claim/WorldPrereq.java @@ -13,14 +13,11 @@ public int getWeight() { @Override public boolean getPassed(@NotNull PrereqClaimData data) { - return data.claimChunk - .getProfileHandler() - .getProfile(data.chunk.getWorld().getName()) - .enabled; + return data.claimChunk().getProfileHandler().getProfile(data.chunk().world()).enabled; } @Override public Optional getErrorMessage(@NotNull PrereqClaimData data) { - return Optional.of(data.claimChunk.getMessages().claimWorldDisabled); + return Optional.of(data.claimChunk().getMessages().claimWorldDisabled); } } diff --git a/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/ClaimCmd.java b/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/ClaimCmd.java index 6d1fcb31..8d310fc0 100644 --- a/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/ClaimCmd.java +++ b/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/ClaimCmd.java @@ -1,6 +1,7 @@ package com.cjburkey.claimchunk.smartcommand.sub.ply; import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.chunk.ChunkPos; import com.cjburkey.claimchunk.smartcommand.CCSubCommand; import de.goldmensch.commanddispatcher.Executor; @@ -42,7 +43,9 @@ public int getRequiredArguments() { @Override public boolean onCall(@NotNull String cmdUsed, @NotNull CommandSender executor, String[] args) { var player = (Player) executor; - claimChunk.getMainHandler().claimChunk(player, player.getLocation().getChunk()); + claimChunk + .getMainHandler() + .claimChunk(player, new ChunkPos(player.getLocation().getChunk())); return true; } } diff --git a/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardApi.java b/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardApi.java index 79884381..fa2e38d9 100644 --- a/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardApi.java +++ b/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardApi.java @@ -2,6 +2,7 @@ import com.cjburkey.claimchunk.ClaimChunk; import com.cjburkey.claimchunk.Utils; +import com.cjburkey.claimchunk.chunk.ChunkPos; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.WorldGuard; @@ -12,7 +13,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import org.bukkit.Chunk; +import java.util.Objects; /** * THIS CLASS IS A RAW IMPLEMENTATION IT WILL CRASH IF WORLD GUARD IS NOT PRESENT USE {@link @@ -48,16 +49,17 @@ static boolean _init(ClaimChunk claimChunk) { return false; } catch (Exception e) { Utils.err("Failed to initialize WorldGuard support"); + //noinspection CallToPrintStackTrace e.printStackTrace(); } return false; } - static boolean _isAllowedClaim(ClaimChunk claimChunk, Chunk chunk) { + static boolean _isAllowedClaim(ClaimChunk claimChunk, ChunkPos chunk) { try { // Generate a region in the given chunk to get all intersecting regions - int bx = chunk.getX() << 4; - int bz = chunk.getZ() << 4; + int bx = chunk.x() << 4; + int bz = chunk.z() << 4; BlockVector3 pt1 = BlockVector3.at(bx, 0, bz); BlockVector3 pt2 = BlockVector3.at(bx + 15, 256, bz + 15); ProtectedCuboidRegion region = new ProtectedCuboidRegion("_", pt1, pt2); @@ -65,7 +67,11 @@ static boolean _isAllowedClaim(ClaimChunk claimChunk, Chunk chunk) { WorldGuard.getInstance() .getPlatform() .getRegionContainer() - .get(BukkitAdapter.adapt(chunk.getWorld())); + .get( + BukkitAdapter.adapt( + Objects.requireNonNull( + claimChunk.getServer().getWorld(chunk.world()), + "World not found!"))); // No regions in this world, claiming should be determined by the config if (regionManager == null) { @@ -81,6 +87,7 @@ static boolean _isAllowedClaim(ClaimChunk claimChunk, Chunk chunk) { // No objections return true; } catch (Exception e) { + //noinspection CallToPrintStackTrace e.printStackTrace(); } diff --git a/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardHandler.java b/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardHandler.java index 2cb9e46a..d89026c9 100644 --- a/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/worldguard/WorldGuardHandler.java @@ -3,8 +3,7 @@ import static com.cjburkey.claimchunk.worldguard.WorldGuardApi.*; import com.cjburkey.claimchunk.ClaimChunk; - -import org.bukkit.Chunk; +import com.cjburkey.claimchunk.chunk.ChunkPos; /** Safe wrapper for {@link com.cjburkey.claimchunk.worldguard.WorldGuardApi} */ public class WorldGuardHandler { @@ -19,7 +18,7 @@ public static boolean init(ClaimChunk claimChunk) { return false; } - public static boolean isAllowedClaim(ClaimChunk claimChunk, Chunk chunk) { + public static boolean isAllowedClaim(ClaimChunk claimChunk, ChunkPos chunk) { try { // If the WorldGuard api never loaded, just allow the claim return (!loaded || _isAllowedClaim(claimChunk, chunk)); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index d3fa7fc2..bc259170 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -45,6 +45,8 @@ chunkOutline: spawnsPerSecond: 2 particlesPerSpawn: 2 heightRadius: 3 + # TODO: NOT IMPLEMENTED + useNewEffect: false worldguard: allowClaimsInRegionsByDefault: true @@ -57,26 +59,29 @@ economy: unclaimReward: 10.0 firstFreeChunks: 0 +floodclaim: + enabled: false + maximumIterations: 6 + maximumArea: 41 + data: saveDataIntervalInMinutes: 10 keepJsonBackups: true minBackupIntervalInMinutes: 120 deleteOldBackupsAfterMinutes: 10080 -database: - useDatabase: false - groupRequests: true - convertOldData: true - hostname: '127.0.0.1' - port: 3306 - database: 'MyServer' - username: 'root' - password: 'root' - printDebug: false - useSsl: false - allowPublicKeyRetrieval: false - -floodclaim: - enabled: true - maximumIterations: 6 - maximumArea: 41 +gui: + menuBackButtonItem: 'minecraft:barrier' + mainMenuCurrentChunkItem: 'minecraft:grass_block' + mainMenuChunkMapItem: 'minecraft:map' + mainMenuPermFlagsItem: 'minecraft:writable_book' + mapMenuUnclaimedItem: 'minecraft:white_wool' + mapMenuSelfClaimedItem: 'minecraft:green_wool' + mapMenuOtherClaimedItem: 'minecraft:blue_wool' + mapMenuCenterUnclaimedItem: 'minecraft:white_glazed_terracotta' + mapMenuCenterSelfClaimedItem: 'minecraft:green_glazed_terracotta' + mapMenuCenterOtherClaimedItem: 'minecraft:blue_glazed_terracotta' + mapMenuAllowClaimOtherChunks: true + permSelectMenuItem: 'minecraft:bow' + permModifyAllowItem: 'minecraft:green_wool' + permModifyDenyItem: 'minecraft:red_wool' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b182d275..2b8e3e71 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,4 +1,6 @@ +# noinspection YAMLSchemaValidation name: '@PLUGIN_NAME@' +# noinspection YAMLSchemaValidation main: '@MAIN_CLASS@' authors: - 'CJ Burkey'