├── .github └── workflows │ ├── maven-publish.yml │ └── maven.yml ├── .gitignore ├── LICENSE ├── README.md ├── images ├── FAQyou.png ├── README.md ├── commandbutton.png ├── configbutton.png ├── installation.png ├── permbutton.png ├── placeholderbutton.png ├── protectionstones.png ├── translationbutton.png └── usage.png ├── logo.png ├── pom.xml └── src └── main ├── java └── dev │ └── espi │ └── protectionstones │ ├── BlockHandler.java │ ├── FlagHandler.java │ ├── ListenerClass.java │ ├── PSCommand.java │ ├── PSConfig.java │ ├── PSEconomy.java │ ├── PSGroupRegion.java │ ├── PSL.java │ ├── PSLocation.java │ ├── PSMergedRegion.java │ ├── PSPlayer.java │ ├── PSProtectBlock.java │ ├── PSRegion.java │ ├── PSRentFlag.java │ ├── PSStandardRegion.java │ ├── ProtectionStones.java │ ├── commands │ ├── ArgAddRemove.java │ ├── ArgAdmin.java │ ├── ArgAdminChangeType.java │ ├── ArgAdminChangeblock.java │ ├── ArgAdminCleanup.java │ ├── ArgAdminFlag.java │ ├── ArgAdminForceMerge.java │ ├── ArgAdminHelp.java │ ├── ArgAdminHide.java │ ├── ArgAdminLastlogon.java │ ├── ArgAdminRecreate.java │ ├── ArgAdminSetTaxAutopayers.java │ ├── ArgAdminStats.java │ ├── ArgBuySell.java │ ├── ArgCount.java │ ├── ArgFlag.java │ ├── ArgGet.java │ ├── ArgGive.java │ ├── ArgHelp.java │ ├── ArgHideUnhide.java │ ├── ArgHome.java │ ├── ArgInfo.java │ ├── ArgList.java │ ├── ArgMerge.java │ ├── ArgName.java │ ├── ArgPriority.java │ ├── ArgRegion.java │ ├── ArgReload.java │ ├── ArgRent.java │ ├── ArgSethome.java │ ├── ArgSetparent.java │ ├── ArgTax.java │ ├── ArgToggle.java │ ├── ArgTp.java │ ├── ArgUnclaim.java │ ├── ArgView.java │ └── PSCommandArg.java │ ├── event │ ├── PSBreakProtectBlockEvent.java │ ├── PSCreateEvent.java │ ├── PSLoseRegion.java │ ├── PSObtainRegion.java │ └── PSRemoveEvent.java │ ├── flags │ ├── FarewellFlagHandler.java │ └── GreetingFlagHandler.java │ ├── gui │ └── GUIScreen.java │ ├── placeholders │ ├── ConfigPlaceholders.java │ ├── PSPlaceholderExpansion.java │ ├── PlayerPlaceholders.java │ └── RegionPlaceholders.java │ └── utils │ ├── BlockUtil.java │ ├── ChatUtil.java │ ├── LimitUtil.java │ ├── MiscUtil.java │ ├── Objs.java │ ├── ParticlesUtil.java │ ├── RecipeUtil.java │ ├── RegionTraverse.java │ ├── TextGUI.java │ ├── UUIDCache.java │ ├── WGMerge.java │ ├── WGUtils.java │ └── upgrade │ ├── ConfigUpgrades.java │ └── LegacyUpgrade.java └── resources ├── block1.toml ├── config.toml └── plugin.yml /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up JDK 16 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: '16' 24 | distribution: 'temurin' 25 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 26 | settings-path: ${{ github.workspace }} # location for the settings.xml file 27 | 28 | - name: Build with Maven 29 | run: mvn -B package --file pom.xml 30 | 31 | - name: Publish to GitHub Packages Apache Maven 32 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 33 | env: 34 | GITHUB_TOKEN: ${{ github.token }} 35 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up JDK 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '21' 23 | distribution: 'temurin' 24 | cache: maven 25 | - name: Build with Maven 26 | run: mvn -B package --file pom.xml 27 | - uses: actions/upload-artifact@v4 28 | with: 29 | name: Artifacts 30 | path: target 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /bin/ 4 | /.settings/ 5 | /ProtectionStones.iml 6 | /.classpath 7 | /.project 8 | /dependency-reduced-pom.xml 9 | /*.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ProtectionStones](/logo.png?raw=true) 2 | 3 | [![Maven Central](https://img.shields.io/maven-central/v/dev.espi/protectionstones.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22dev.espi%22%20AND%20a:%22protectionstones%22) 4 | ![Open issues](https://img.shields.io/github/issues-raw/espidev/ProtectionStones) 5 | ![Closed issues](https://img.shields.io/github/issues-closed-raw/espidev/ProtectionStones) 6 | 7 | [Spigot](https://www.spigotmc.org/resources/protectionstones-updated-for-1-13-1-16-wg7.61797/) | [Permissions](https://espidev.gitbook.io/protectionstones/permissions) | [Commands](https://espidev.gitbook.io/protectionstones/commands) | [Configuration](https://espidev.gitbook.io/protectionstones/configuration) | [Placeholders](https://espidev.gitbook.io/protectionstones/placeholders) | [Translations](https://espidev.gitbook.io/protectionstones/translations) | [API Information](https://espidev.gitbook.io/protectionstones/api) | [Javadocs](https://jdps.espi.dev/) | [Dev Builds](https://ci.espi.dev/job/ProtectionStones/) 8 | 9 | Get support for the plugin on the M.O.S.S. Discord! https://discord.gg/cqM96tcJRx 10 | 11 | ProtectionStones is a grief prevention and land claiming plugin. 12 | 13 | This plugin uses a specified type of minecraft block/blocks as a protection block. When a player placed a block of that type, they are able to protect a region around them. The size of the protected region is configurable in the plugins config file. You can also set which flags players can change and also the default flags to be set when a new region is created. 14 | 15 | View the Spigot page (with FAQ and install instructions) [here](https://www.spigotmc.org/resources/protectionstones-updated-for-1-13-1-16-wg7.61797/). 16 | 17 | Check the [wiki](https://github.com/espidev/ProtectionStones/wiki) for plugin reference information. 18 | 19 | ### Dependencies 20 | * ProtectionStones 2.10.5 21 | * Spigot 1.20.6+ 22 | * WorldGuard 7.0.9+ 23 | * WorldEdit 7.2.6+ 24 | * Vault (Optional) 25 | * PlaceholderAPI (Optional) 26 | * LuckPerms (Optional) 27 | 28 | ### Building 29 | Make sure you have the Java 21 JDK installed, as well as Maven. 30 | 31 | ``` 32 | git clone https://github.com/espidev/ProtectionStones.git 33 | cd ProtectionStones 34 | mvn clean install 35 | ``` 36 | 37 | Compiling ProtectionStones will also produce a jar with JavaDocs, which can be useful if you need documentation for an older version. 38 | 39 | ### Usage Statistics 40 | 41 | 42 | View full usage statistics [here](https://bstats.org/plugin/bukkit/ProtectionStones/4071). 43 | 44 | This plugin is licensed under the **GPLv3**, as is required by Bukkit plugins. 45 | -------------------------------------------------------------------------------- /images/FAQyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/FAQyou.png -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | Images 2 | -------------------------------------------------------------------------------- /images/commandbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/commandbutton.png -------------------------------------------------------------------------------- /images/configbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/configbutton.png -------------------------------------------------------------------------------- /images/installation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/installation.png -------------------------------------------------------------------------------- /images/permbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/permbutton.png -------------------------------------------------------------------------------- /images/placeholderbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/placeholderbutton.png -------------------------------------------------------------------------------- /images/protectionstones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/protectionstones.png -------------------------------------------------------------------------------- /images/translationbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/translationbutton.png -------------------------------------------------------------------------------- /images/usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/images/usage.png -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espidev/ProtectionStones/15654970ae24e2b1a31eb3a90592a55bcd392122/logo.png -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/PSCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones; 17 | 18 | import dev.espi.protectionstones.commands.*; 19 | import org.bukkit.ChatColor; 20 | import org.bukkit.command.Command; 21 | import org.bukkit.command.CommandSender; 22 | import org.bukkit.command.ConsoleCommandSender; 23 | import org.bukkit.entity.Player; 24 | import org.bukkit.util.StringUtil; 25 | 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | 30 | public class PSCommand extends Command { 31 | 32 | PSCommand(String name) { 33 | super(name); 34 | } 35 | 36 | static void addDefaultArguments() { 37 | ProtectionStones.getInstance().addCommandArgument(new ArgAddRemove()); 38 | ProtectionStones.getInstance().addCommandArgument(new ArgAdmin()); 39 | ProtectionStones.getInstance().addCommandArgument(new ArgBuySell()); 40 | ProtectionStones.getInstance().addCommandArgument(new ArgCount()); 41 | ProtectionStones.getInstance().addCommandArgument(new ArgFlag()); 42 | ProtectionStones.getInstance().addCommandArgument(new ArgGet()); 43 | ProtectionStones.getInstance().addCommandArgument(new ArgGive()); 44 | ProtectionStones.getInstance().addCommandArgument(new ArgHideUnhide()); 45 | ProtectionStones.getInstance().addCommandArgument(new ArgHome()); 46 | ProtectionStones.getInstance().addCommandArgument(new ArgInfo()); 47 | ProtectionStones.getInstance().addCommandArgument(new ArgList()); 48 | ProtectionStones.getInstance().addCommandArgument(new ArgMerge()); 49 | ProtectionStones.getInstance().addCommandArgument(new ArgName()); 50 | ProtectionStones.getInstance().addCommandArgument(new ArgPriority()); 51 | ProtectionStones.getInstance().addCommandArgument(new ArgRegion()); 52 | ProtectionStones.getInstance().addCommandArgument(new ArgReload()); 53 | ProtectionStones.getInstance().addCommandArgument(new ArgRent()); 54 | ProtectionStones.getInstance().addCommandArgument(new ArgSethome()); 55 | ProtectionStones.getInstance().addCommandArgument(new ArgSetparent()); 56 | ProtectionStones.getInstance().addCommandArgument(new ArgTax()); 57 | ProtectionStones.getInstance().addCommandArgument(new ArgToggle()); 58 | ProtectionStones.getInstance().addCommandArgument(new ArgToggle.ArgToggleOn()); 59 | ProtectionStones.getInstance().addCommandArgument(new ArgToggle.ArgToggleOff()); 60 | ProtectionStones.getInstance().addCommandArgument(new ArgTp()); 61 | ProtectionStones.getInstance().addCommandArgument(new ArgUnclaim()); 62 | ProtectionStones.getInstance().addCommandArgument(new ArgView()); 63 | ProtectionStones.getInstance().addCommandArgument(new ArgHelp()); 64 | } 65 | 66 | @Override 67 | public List tabComplete(CommandSender sender, String alias, String[] args) { 68 | if (args.length == 1) { 69 | List l = new ArrayList<>(); 70 | for (PSCommandArg ps : ProtectionStones.getInstance().getCommandArguments()) { 71 | boolean hasPerm = false; 72 | if (ps.getPermissionsToExecute() == null) { 73 | hasPerm = true; 74 | } else { 75 | for (String perm : ps.getPermissionsToExecute()) { 76 | if (sender.hasPermission(perm)) { 77 | hasPerm = true; 78 | break; 79 | } 80 | } 81 | } 82 | if (hasPerm) l.addAll(ps.getNames()); 83 | } 84 | return StringUtil.copyPartialMatches(args[0], l, new ArrayList<>()); 85 | } else if (args.length >= 2) { 86 | for (PSCommandArg ps : ProtectionStones.getInstance().getCommandArguments()) { 87 | for (String arg : ps.getNames()) { 88 | if (arg.equalsIgnoreCase(args[0])) { 89 | return ps.tabComplete(sender, alias, args); 90 | } 91 | } 92 | } 93 | } 94 | return null; 95 | } 96 | 97 | @Override 98 | public boolean execute(CommandSender s, String label, String[] args) { 99 | if (args.length == 0) { // no arguments 100 | if (s instanceof ConsoleCommandSender) { 101 | s.sendMessage(ChatColor.RED + "You can only use /ps reload, /ps admin, /ps give from console."); 102 | } else { 103 | new ArgHelp().executeArgument(s, args, null); 104 | } 105 | return true; 106 | } 107 | for (PSCommandArg command : ProtectionStones.getInstance().getCommandArguments()) { 108 | if (command.getNames().contains(args[0])) { 109 | if (command.allowNonPlayersToExecute() || s instanceof Player) { 110 | 111 | // extract flags 112 | List nArgs = new ArrayList<>(); 113 | HashMap flags = new HashMap<>(); 114 | for (int i = 0; i < args.length; i++) { 115 | 116 | if (command.getRegisteredFlags() != null && command.getRegisteredFlags().containsKey(args[i])) { 117 | if (command.getRegisteredFlags().get(args[i])) { // has value after 118 | if (i != args.length-1) { 119 | flags.put(args[i], args[++i]); 120 | } 121 | } else { 122 | flags.put(args[i], null); 123 | } 124 | } else { 125 | nArgs.add(args[i]); 126 | } 127 | } 128 | 129 | return command.executeArgument(s, nArgs.toArray(new String[0]), flags); 130 | } else if (!command.allowNonPlayersToExecute()) { 131 | s.sendMessage(ChatColor.RED + "You can only use /ps reload, /ps admin, /ps give from console."); 132 | return true; 133 | } 134 | } 135 | } 136 | 137 | PSL.msg(s, PSL.NO_SUCH_COMMAND.msg()); 138 | return true; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/PSLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones; 17 | 18 | public class PSLocation { 19 | public int x, y, z; 20 | public PSLocation(int x, int y, int z) { 21 | this.x = x; 22 | this.y = y; 23 | this.z = z; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/PSProtectBlock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones; 17 | 18 | import com.electronwill.nightconfig.core.conversion.Path; 19 | import com.electronwill.nightconfig.core.conversion.SpecDoubleInRange; 20 | import com.electronwill.nightconfig.core.conversion.SpecIntInRange; 21 | import com.sk89q.worldguard.protection.flags.Flag; 22 | import org.bukkit.inventory.ItemStack; 23 | 24 | import java.util.HashMap; 25 | import java.util.LinkedHashMap; 26 | import java.util.List; 27 | 28 | /** 29 | * Object to represent a protection block as defined in config (blocks folder). The fields are the exact same as 30 | * the ones in the config. 31 | */ 32 | 33 | public class PSProtectBlock { 34 | 35 | // Annotations are for types that have names that aren't the same as the config name 36 | // Check here for help: https://github.com/TheElectronWill/Night-Config 37 | 38 | // main section 39 | public String type, alias; 40 | @Path("description") 41 | public String description; 42 | @Path("restrict_obtaining") 43 | public boolean restrictObtaining; 44 | @Path("world_list_type") 45 | public String worldListType; 46 | @Path("worlds") 47 | public List worlds; 48 | @Path("prevent_block_place_in_restricted_world") 49 | public boolean preventBlockPlaceInRestrictedWorld; 50 | @Path("allow_placing_in_wild") 51 | public boolean allowPlacingInWild; 52 | @Path("placing_bypasses_wg_passthrough") 53 | public Boolean placingBypassesWGPassthrough; 54 | 55 | // region section 56 | @Path("region.distance_between_claims") 57 | public int distanceBetweenClaims; 58 | @Path("region.x_radius") 59 | @SpecIntInRange(min = 0, max = Integer.MAX_VALUE) 60 | public int xRadius; 61 | @Path("region.y_radius") 62 | @SpecIntInRange(min = -1, max = Integer.MAX_VALUE) 63 | public int yRadius; 64 | @Path("region.z_radius") 65 | @SpecIntInRange(min = 0, max = Integer.MAX_VALUE) 66 | public int zRadius; 67 | @Path("region.chunk_radius") 68 | @SpecIntInRange(min = -1, max = Integer.MAX_VALUE) 69 | public int chunkRadius; 70 | @Path("region.home_x_offset") 71 | public double homeXOffset; 72 | @Path("region.home_y_offset") 73 | public double homeYOffset; 74 | @Path("region.home_z_offset") 75 | public double homeZOffset; 76 | @Path("region.flags") 77 | public List flags; 78 | @Path("region.allowed_flags") 79 | public List allowedFlagsRaw; 80 | @Path("region.hidden_flags_from_info") 81 | public List hiddenFlagsFromInfo; 82 | @Path("region.priority") 83 | public int priority; 84 | @Path("region.allow_overlap_unowned_regions") 85 | public boolean allowOverlapUnownedRegions; 86 | @Path("region.allow_other_regions_to_overlap") 87 | public String allowOtherRegionsToOverlap; 88 | @Path("region.allow_merging") 89 | public boolean allowMerging; 90 | @Path("region.allowed_merging_into_types") 91 | public List allowedMergingIntoTypes; 92 | 93 | // block data section 94 | @Path("block_data.display_name") 95 | public String displayName; 96 | @Path("block_data.lore") 97 | public List lore; 98 | @Path("block_data.enchanted_effect") 99 | public boolean enchantedEffect; 100 | @Path("block_data.price") 101 | @SpecDoubleInRange(min = 0.0, max = Double.MAX_VALUE) 102 | public double price; 103 | @Path("block_data.allow_craft_with_custom_recipe") 104 | public boolean allowCraftWithCustomRecipe; 105 | @Path("block_data.custom_recipe") 106 | public List> customRecipe; 107 | @Path("block_data.recipe_amount") 108 | @SpecIntInRange(min = 0, max = 64) 109 | public int recipeAmount; 110 | @Path("block_data.custom_model_data") 111 | public int customModelData; 112 | 113 | // economy section 114 | @Path("economy.tax_amount") 115 | public double taxAmount; 116 | @Path("economy.tax_period") 117 | @SpecIntInRange(min = -1, max = Integer.MAX_VALUE) 118 | public int taxPeriod; 119 | @Path("economy.tax_payment_time") 120 | @SpecIntInRange(min = 1, max = Integer.MAX_VALUE) 121 | public int taxPaymentTime; 122 | @Path("economy.start_with_tax_autopay") 123 | public boolean startWithTaxAutopay; 124 | @Path("economy.tenant_rent_role") 125 | public String tenantRentRole; 126 | @Path("economy.landlord_still_owner") 127 | public boolean landlordStillOwner; 128 | 129 | // behaviour section 130 | @Path("behaviour.auto_hide") 131 | public boolean autoHide; 132 | @Path("behaviour.auto_merge") 133 | public boolean autoMerge; 134 | @Path("behaviour.no_drop") 135 | public boolean noDrop; 136 | @Path("behaviour.prevent_piston_push") 137 | public boolean preventPistonPush; 138 | @Path("behaviour.prevent_explode") 139 | public boolean preventExplode; 140 | @Path("behaviour.destroy_region_when_explode") 141 | public boolean destroyRegionWhenExplode; 142 | @Path("behaviour.prevent_silk_touch") 143 | public boolean preventSilkTouch; 144 | @Path("behaviour.cost_to_place") 145 | @SpecDoubleInRange(min = 0.0, max = Double.MAX_VALUE) 146 | public double costToPlace; 147 | @Path("behaviour.allow_smelt_item") 148 | public boolean allowSmeltItem; 149 | @Path("behaviour.allow_use_in_crafting") 150 | public boolean allowUseInCrafting; 151 | 152 | // player section 153 | @Path("player.allow_shift_right_break") 154 | public boolean allowShiftRightBreak; 155 | @Path("player.prevent_teleport_in") 156 | public boolean preventTeleportIn; 157 | @Path("player.no_moving_when_tp_waiting") 158 | public boolean noMovingWhenTeleportWaiting; 159 | @Path("player.tp_waiting_seconds") 160 | @SpecIntInRange(min = 0, max = Integer.MAX_VALUE) 161 | public int tpWaitingSeconds; 162 | @Path("player.prevent_ps_get") 163 | public boolean preventPsGet; 164 | @Path("player.prevent_ps_home") 165 | public boolean preventPsHome; 166 | @Path("player.permission") 167 | public String permission; 168 | 169 | // event section 170 | @Path("event.enable") 171 | public boolean eventsEnabled; 172 | @Path("event.on_region_create") 173 | public List regionCreateCommands; 174 | @Path("event.on_region_destroy") 175 | public List regionDestroyCommands; 176 | 177 | 178 | // non-config items 179 | public HashMap, Object> regionFlags = new HashMap<>(); 180 | public LinkedHashMap> allowedFlags = new LinkedHashMap<>(); 181 | 182 | /** 183 | * Get the protection block item for this specific protection block. 184 | * 185 | * @return the item with NBT and other metadata to signify that it was created by protection stones 186 | */ 187 | public ItemStack createItem() { 188 | return ProtectionStones.createProtectBlockItem(this); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/PSRentFlag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones; 17 | 18 | public enum PSRentFlag { 19 | TENANT_IS_OWNER("false"), 20 | LANDLORD_IS_OWNER("false"); 21 | 22 | String val; 23 | 24 | PSRentFlag(String val) { 25 | this.val = val; 26 | } 27 | 28 | public String getVal() { 29 | return val; 30 | } 31 | 32 | public void setVal(String val) { 33 | this.val = val; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdmin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.utils.upgrade.LegacyUpgrade; 20 | import dev.espi.protectionstones.PSL; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.command.CommandSender; 25 | import org.bukkit.util.StringUtil; 26 | 27 | import java.util.*; 28 | 29 | /* 30 | * To add new sub commands, add them here, and in ArgAdminHelp manually 31 | */ 32 | 33 | public class ArgAdmin implements PSCommandArg { 34 | 35 | // has to be a method, because the base command config option is not available until the plugin is loaded 36 | public static String getCleanupHelp() { 37 | return ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + ProtectionStones.getInstance().getConfigOptions().base_command + 38 | " admin cleanup [remove|preview] [-t typealias (optional)] [days] [world (optional)]"; 39 | } 40 | 41 | public static String getFlagHelp() { 42 | return ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + ProtectionStones.getInstance().getConfigOptions().base_command + 43 | " admin flag [world] [flagname] [value|null|default]"; 44 | } 45 | 46 | public static String getChangeBlockHelp() { 47 | return ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + ProtectionStones.getInstance().getConfigOptions().base_command + 48 | " admin changeblock [world] [oldtypealias] [newtypealias]"; 49 | } 50 | 51 | public static String getChangeRegionTypeHelp() { 52 | return ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + ProtectionStones.getInstance().getConfigOptions().base_command + 53 | " admin changeregiontype [world] [oldtype] [newtype]"; 54 | } 55 | 56 | public static String getForceMergeHelp() { 57 | return ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + ProtectionStones.getInstance().getConfigOptions().base_command + 58 | " admin forcemerge [world]"; 59 | } 60 | 61 | @Override 62 | public List getNames() { 63 | return Collections.singletonList("admin"); 64 | } 65 | 66 | @Override 67 | public boolean allowNonPlayersToExecute() { 68 | return true; 69 | } 70 | 71 | @Override 72 | public List getPermissionsToExecute() { 73 | return Collections.singletonList("protectionstones.admin"); 74 | } 75 | 76 | @Override 77 | public HashMap getRegisteredFlags() { 78 | return null; 79 | } 80 | 81 | // /ps admin [arg] 82 | @Override 83 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 84 | if (!s.hasPermission("protectionstones.admin")) { 85 | return PSL.msg(s, PSL.NO_PERMISSION_ADMIN.msg()); 86 | } 87 | 88 | if (args.length < 2) { 89 | ArgAdminHelp.argumentAdminHelp(s, args); 90 | return true; 91 | } 92 | 93 | switch (args[1].toLowerCase()) { 94 | case "help": 95 | return ArgAdminHelp.argumentAdminHelp(s, args); 96 | case "version": 97 | s.sendMessage(ChatColor.AQUA + "ProtectionStones: " + ChatColor.GRAY + ProtectionStones.getInstance().getDescription().getVersion()); 98 | s.sendMessage(ChatColor.AQUA + "Developers: " + ChatColor.GRAY + ProtectionStones.getInstance().getDescription().getAuthors()); 99 | s.sendMessage(ChatColor.AQUA + "Bukkit: " + ChatColor.GRAY + Bukkit.getVersion()); 100 | s.sendMessage(ChatColor.AQUA + "WG: " + ChatColor.GRAY + WorldGuardPlugin.inst().getDescription().getVersion()); 101 | break; 102 | case "hide": 103 | return ArgAdminHide.argumentAdminHide(s, args); 104 | case "unhide": 105 | return ArgAdminHide.argumentAdminHide(s, args); 106 | case "cleanup": 107 | return ArgAdminCleanup.argumentAdminCleanup(s, args); 108 | case "stats": 109 | return ArgAdminStats.argumentAdminStats(s, args); 110 | case "lastlogon": 111 | return ArgAdminLastlogon.argumentAdminLastLogon(s, args); 112 | case "lastlogons": 113 | return ArgAdminLastlogon.argumentAdminLastLogons(s, args); 114 | case "flag": 115 | return ArgAdminFlag.argumentAdminFlag(s, args); 116 | case "recreate": 117 | return ArgAdminRecreate.argumentAdminRecreate(s, args); 118 | case "changeblock": 119 | return ArgAdminChangeblock.argumentAdminChangeblock(s, args); 120 | case "changeregiontype": 121 | return ArgAdminChangeType.argumentAdminChangeType(s, args); 122 | case "forcemerge": 123 | return ArgAdminForceMerge.argumentAdminForceMerge(s, args); 124 | case "settaxautopayers": 125 | return ArgAdminSetTaxAutopayers.argumentAdminSetTaxAutopayers(s, args); 126 | case "fixregions": 127 | s.sendMessage(ChatColor.YELLOW + "Fixing..."); 128 | LegacyUpgrade.upgradeRegions(); 129 | s.sendMessage(ChatColor.YELLOW + "Done!"); 130 | break; 131 | case "debug": 132 | if (ProtectionStones.getInstance().isDebug()) { 133 | s.sendMessage(ChatColor.YELLOW + "Debug mode is now off."); 134 | ProtectionStones.getInstance().setDebug(false); 135 | } else { 136 | s.sendMessage(ChatColor.YELLOW + "Debug mode is now on."); 137 | ProtectionStones.getInstance().setDebug(true); 138 | } 139 | } 140 | return true; 141 | } 142 | 143 | @Override 144 | public List tabComplete(CommandSender sender, String alias, String[] args) { 145 | if (args.length == 2) { 146 | List arg = Arrays.asList("version", "hide", "unhide", "cleanup", "stats", "lastlogon", "lastlogons", "flag", "recreate", "fixregions", "debug", "forcemerge", "changeblock", "changeregiontype", "settaxautopayers"); 147 | return StringUtil.copyPartialMatches(args[1], arg, new ArrayList<>()); 148 | } else if (args.length >= 3 && args[1].equals("forcemerge")) { 149 | return ArgAdminForceMerge.tabComplete(sender, alias, args); 150 | } 151 | return null; 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminChangeType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.commands; 19 | 20 | import com.sk89q.worldguard.protection.managers.RegionManager; 21 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 22 | import dev.espi.protectionstones.FlagHandler; 23 | import dev.espi.protectionstones.PSL; 24 | import dev.espi.protectionstones.utils.WGUtils; 25 | import org.bukkit.Bukkit; 26 | import org.bukkit.ChatColor; 27 | import org.bukkit.World; 28 | import org.bukkit.command.CommandSender; 29 | 30 | import java.util.HashSet; 31 | import java.util.Set; 32 | 33 | class ArgAdminChangeType { 34 | 35 | // /ps admin changeregiontype [world] [fromblocktype] [toblocktype] 36 | static boolean argumentAdminChangeType(CommandSender p, String[] args) { 37 | if (args.length < 5) { 38 | return PSL.msg(p, ArgAdmin.getChangeRegionTypeHelp()); 39 | } 40 | 41 | World w = Bukkit.getWorld(args[2]); 42 | if (w == null) { 43 | return PSL.msg(p, PSL.INVALID_WORLD.msg()); 44 | } 45 | 46 | RegionManager rgm = WGUtils.getRegionManagerWithWorld(w); 47 | if (rgm == null) { 48 | return PSL.msg(p, ChatColor.GRAY + "The world does not have WorldGuard configured!"); 49 | } 50 | 51 | String fromType = args[3], toType = args[4]; 52 | 53 | // loop through and update flags manually (do not rely on PSRegion API, since this can include invalid regions) 54 | for (ProtectedRegion r : rgm.getRegions().values()) { 55 | // update block material 56 | if (r.getFlag(FlagHandler.PS_BLOCK_MATERIAL) != null && r.getFlag(FlagHandler.PS_BLOCK_MATERIAL).equals(fromType)) { 57 | r.setFlag(FlagHandler.PS_BLOCK_MATERIAL, toType); 58 | p.sendMessage(ChatColor.GRAY + "Updated region " + r.getId()); 59 | } 60 | // update merged regions 61 | if (r.getFlag(FlagHandler.PS_MERGED_REGIONS_TYPES) != null) { 62 | Set s = new HashSet<>(); 63 | for (String entry : r.getFlag(FlagHandler.PS_MERGED_REGIONS_TYPES)) { 64 | String[] spl = entry.split(" "); 65 | 66 | if (spl.length == 2) { 67 | if (spl[1].equals(fromType)) { // if it is of the type to change 68 | p.sendMessage(ChatColor.GRAY + "Updated merged region " + spl[0]); 69 | s.add(spl[0] + " " + toType); 70 | } else { 71 | s.add(entry); 72 | } 73 | } 74 | 75 | } 76 | 77 | r.setFlag(FlagHandler.PS_MERGED_REGIONS_TYPES, s); 78 | } 79 | } 80 | 81 | p.sendMessage(ChatColor.GREEN + "Finished!"); 82 | p.sendMessage(ChatColor.GRAY + "You should restart the server, and make sure the new block type is configured in the config."); 83 | return true; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminChangeblock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.protection.managers.RegionManager; 19 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 20 | import dev.espi.protectionstones.*; 21 | import dev.espi.protectionstones.utils.WGUtils; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.World; 25 | import org.bukkit.command.CommandSender; 26 | 27 | import java.util.function.Consumer; 28 | 29 | class ArgAdminChangeblock { 30 | 31 | // /ps admin changeblock [world] [fromblockalias] [toblockalias] 32 | static boolean argumentAdminChangeblock(CommandSender p, String[] args) { 33 | if (args.length < 5) { 34 | PSL.msg(p, ArgAdmin.getChangeBlockHelp()); 35 | return true; 36 | } 37 | 38 | String world = args[2], fromBlockAlias = args[3], toBlockAlias = args[4]; 39 | if (ProtectionStones.getProtectBlockFromAlias(fromBlockAlias) == null) { 40 | PSL.msg(p, ChatColor.GRAY + "The type to change from is not a registered protection block!"); 41 | return true; 42 | } 43 | if (ProtectionStones.getProtectBlockFromAlias(toBlockAlias) == null) { 44 | PSL.msg(p, ChatColor.GRAY + "The type to change to is not a registered protection block!"); 45 | return true; 46 | } 47 | 48 | String fromBlock = ProtectionStones.getProtectBlockFromAlias(fromBlockAlias).type, 49 | toBlock = ProtectionStones.getProtectBlockFromAlias(toBlockAlias).type; 50 | 51 | Consumer convertFunction = (region) -> { 52 | if (region.getType().equals(fromBlock)) { 53 | p.sendMessage(ChatColor.GRAY + "Changing " + region.getId() + "..."); 54 | 55 | region.setType(ProtectionStones.getBlockOptions(toBlock)); 56 | } 57 | }; 58 | 59 | World w = Bukkit.getWorld(world); 60 | if (w == null) { 61 | return PSL.msg(p, PSL.INVALID_WORLD.msg()); 62 | } 63 | RegionManager rgm = WGUtils.getRegionManagerWithWorld(w); 64 | if (rgm == null) { 65 | return PSL.msg(p, ChatColor.GRAY + "The world does not have WorldGuard configured!"); 66 | } 67 | for (ProtectedRegion r : rgm.getRegions().values()) { 68 | if (ProtectionStones.isPSRegion(r)) { 69 | PSRegion pr = PSRegion.fromWGRegion(w, r); 70 | 71 | convertFunction.accept(pr); 72 | 73 | if (pr instanceof PSGroupRegion) { 74 | for (PSMergedRegion psmr : ((PSGroupRegion) pr).getMergedRegions()) { 75 | convertFunction.accept(psmr); 76 | } 77 | } 78 | } 79 | } 80 | 81 | p.sendMessage(ChatColor.GRAY + "Done!"); 82 | 83 | return true; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminFlag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.protection.managers.RegionManager; 19 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 20 | import dev.espi.protectionstones.FlagHandler; 21 | import dev.espi.protectionstones.PSL; 22 | import dev.espi.protectionstones.PSRegion; 23 | import dev.espi.protectionstones.ProtectionStones; 24 | import dev.espi.protectionstones.utils.UUIDCache; 25 | import dev.espi.protectionstones.utils.WGUtils; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.World; 28 | import org.bukkit.command.CommandSender; 29 | 30 | class ArgAdminFlag { 31 | static boolean argumentAdminFlag(CommandSender p, String[] args) { 32 | 33 | if (args.length < 5) { 34 | PSL.msg(p, ArgAdmin.getFlagHelp()); 35 | return true; 36 | } 37 | 38 | String flag, value = "", gee = ""; 39 | World w = Bukkit.getWorld(args[2]); 40 | if (w == null) 41 | return PSL.msg(p, PSL.INVALID_WORLD.msg()); 42 | 43 | if (args[3].equalsIgnoreCase("-g")) { 44 | flag = args[5]; 45 | for (int i = 6; i < args.length; i++) value += args[i] + " "; 46 | gee = args[4]; 47 | } else { 48 | flag = args[3]; 49 | for (int i = 4; i < args.length; i++) value += args[i] + " "; 50 | } 51 | 52 | if (WGUtils.getFlagRegistry().get(flag) == null) 53 | return PSL.msg(p, PSL.FLAG_NOT_SET.msg()); 54 | 55 | final String fValue = value, fGee = gee; 56 | RegionManager rgm = WGUtils.getRegionManagerWithWorld(w); 57 | for (ProtectedRegion r : rgm.getRegions().values()) { 58 | if (ProtectionStones.isPSRegion(r) && PSRegion.fromWGRegion(w, r) != null) { 59 | String flagValue = fValue; 60 | 61 | // apply %player% placeholder 62 | if (FlagHandler.getPlayerPlaceholderFlags().contains(flag) && (!r.getOwners().getUniqueIds().isEmpty())) { 63 | String name = UUIDCache.getNameFromUUID(r.getOwners().getUniqueIds().stream().findFirst().get()); 64 | if (name != null) { 65 | flagValue = flagValue.replace("%player%", name); 66 | } 67 | } 68 | 69 | ArgFlag.setFlag(PSRegion.fromWGRegion(w, r), p, flag, flagValue.trim(), fGee); 70 | } 71 | } 72 | return true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminHelp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.ProtectionStones; 19 | import net.md_5.bungee.api.chat.ComponentBuilder; 20 | import net.md_5.bungee.api.chat.HoverEvent; 21 | import net.md_5.bungee.api.chat.TextComponent; 22 | import org.bukkit.ChatColor; 23 | import org.bukkit.command.CommandSender; 24 | 25 | public class ArgAdminHelp { 26 | 27 | private static void send(CommandSender p, String text, String info) { 28 | TextComponent tc = new TextComponent(text); 29 | tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(info).create())); 30 | p.spigot().sendMessage(tc); 31 | } 32 | 33 | static boolean argumentAdminHelp(CommandSender p, String[] args) { 34 | String bc = "/" + ProtectionStones.getInstance().getConfigOptions().base_command; 35 | 36 | p.sendMessage(ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " PS Admin Help " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "=====\n" + ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps admin help"); 37 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin version", "Show the version number of the plugin."); 38 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin hide", "Hide all of the protection stone blocks in the world you are in."); 39 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin unhide", "Unhide all of the protection stone blocks in the world you are in."); 40 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin cleanup remove [days] [-t typealias (optional)] [world (console)]", "Remove inactive players that haven't joined within the last [days] days from protected regions in the world you are in (or specified). Then, remove any regions with no owners left."); 41 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin cleanup disown [days] [-t typealias (optional)] [world (console)]", "Remove inactive players that haven't joined within the last [days] days from protected regions in the world you are in (or specified)."); 42 | send(p, ArgAdmin.getFlagHelp(), "Set a flag for all protection stone regions in a world."); 43 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin lastlogon [player]", "Get the last time a player logged on."); 44 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin lastlogons", "List all of the last logons of each player."); 45 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin stats [player (optional)]", "Show some statistics of the plugin."); 46 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin recreate", "Recreate all PS regions using radius set in config."); 47 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin debug", "Toggles debug mode."); 48 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin settaxautopayers", "Add a tax autopayer for every region on the server that does not have one."); 49 | send(p, ArgAdmin.getForceMergeHelp(), "Merge overlapping PS regions together if they have the same owners, members and flags."); 50 | send(p, ArgAdmin.getChangeBlockHelp(), "Change all of the PS blocks and regions in a world to a different block. Both blocks must be configured in config."); 51 | send(p, ArgAdmin.getChangeRegionTypeHelp(), "Change the internal type of all PS regions of a certain type. Useful for error correction."); 52 | send(p, ChatColor.AQUA + "> " + ChatColor.GRAY + bc + " admin fixregions", "Use this command to recalculate block types for PS regions in a world."); 53 | 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminHide.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.protection.managers.RegionManager; 19 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 20 | import dev.espi.protectionstones.PSL; 21 | import dev.espi.protectionstones.PSRegion; 22 | import dev.espi.protectionstones.ProtectionStones; 23 | import dev.espi.protectionstones.utils.WGUtils; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.World; 26 | import org.bukkit.command.CommandSender; 27 | import org.bukkit.entity.Player; 28 | 29 | class ArgAdminHide { 30 | 31 | // /ps admin hide 32 | static boolean argumentAdminHide(CommandSender p, String[] args) { 33 | RegionManager mgr; 34 | World w; 35 | if (p instanceof Player) { 36 | mgr = WGUtils.getRegionManagerWithPlayer((Player) p); 37 | w = ((Player) p).getWorld(); 38 | } else { 39 | if (args.length != 3) { 40 | PSL.msg(p, PSL.ADMIN_CONSOLE_WORLD.msg()); 41 | return true; 42 | } 43 | if (Bukkit.getWorld(args[2]) == null) { 44 | PSL.msg(p, PSL.INVALID_WORLD.msg()); 45 | return true; 46 | } 47 | w = Bukkit.getWorld(args[2]); 48 | mgr = WGUtils.getRegionManagerWithWorld(w); 49 | } 50 | 51 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 52 | // loop through regions that are protection stones and hide or unhide the block 53 | for (ProtectedRegion r : mgr.getRegions().values()) { 54 | if (ProtectionStones.isPSRegion(r)) { 55 | PSRegion region = PSRegion.fromWGRegion(w, r); 56 | if (args[1].equalsIgnoreCase("hide")) { 57 | Bukkit.getScheduler().runTask(ProtectionStones.getInstance(), region::hide); 58 | } else if (args[1].equalsIgnoreCase("unhide")){ 59 | Bukkit.getScheduler().runTask(ProtectionStones.getInstance(), region::unhide); 60 | } 61 | } 62 | } 63 | 64 | String hMessage = args[1].equalsIgnoreCase("unhide") ? "unhidden" : "hidden"; 65 | PSL.msg(p, PSL.ADMIN_HIDE_TOGGLED.msg() 66 | .replace("%message%", hMessage)); 67 | }); 68 | 69 | return true; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminLastlogon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import org.bukkit.Bukkit; 20 | import org.bukkit.OfflinePlayer; 21 | import org.bukkit.command.CommandSender; 22 | 23 | import java.util.Arrays; 24 | import java.util.Comparator; 25 | 26 | class ArgAdminLastlogon { 27 | // /ps admin lastlogon 28 | 29 | static class PlayerComparator implements Comparator { 30 | @Override 31 | public int compare(OfflinePlayer o1, OfflinePlayer o2) { 32 | return o1.getName().compareTo(o2.getName()); 33 | } 34 | } 35 | static boolean argumentAdminLastLogon(CommandSender p, String[] args) { 36 | if (args.length < 3) { 37 | p.sendMessage(PSL.COMMAND_REQUIRES_PLAYER_NAME.msg()); 38 | return true; 39 | } 40 | OfflinePlayer op = Bukkit.getOfflinePlayer(args[2]); 41 | 42 | String playerName = args[2]; 43 | long lastPlayed = (System.currentTimeMillis() - op.getLastPlayed()) / 86400000L; 44 | 45 | PSL.msg(p, PSL.ADMIN_LAST_LOGON.msg() 46 | .replace("%player%", playerName) 47 | .replace("%days%", "" +lastPlayed)); 48 | 49 | if (op.isBanned()) { 50 | PSL.msg(p, PSL.ADMIN_IS_BANNED.msg() 51 | .replace("%player%", playerName)); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | // /ps admin lastlogons 58 | static boolean argumentAdminLastLogons(CommandSender p, String[] args) { 59 | int days = 0; 60 | if (args.length > 2) { 61 | try { 62 | days = Integer.parseInt(args[2]); 63 | } catch (Exception e) { 64 | PSL.msg(p, PSL.ADMIN_ERROR_PARSING.msg()); 65 | return true; 66 | } 67 | } 68 | OfflinePlayer[] offlinePlayerList = Bukkit.getServer().getOfflinePlayers().clone(); 69 | int playerCounter = 0; 70 | PSL.msg(p, PSL.ADMIN_LASTLOGONS_HEADER.msg() 71 | .replace("%days%", "" + days)); 72 | 73 | Arrays.sort(offlinePlayerList, new PlayerComparator()); 74 | for (OfflinePlayer offlinePlayer : offlinePlayerList) { 75 | long lastPlayed = (System.currentTimeMillis() - offlinePlayer.getLastPlayed()) / 86400000L; 76 | if (lastPlayed >= days) { 77 | playerCounter++; 78 | PSL.msg(p, PSL.ADMIN_LASTLOGONS_LINE.msg() 79 | .replace("%player%", offlinePlayer.getName()) 80 | .replace("%time%", "" + lastPlayed)); 81 | } 82 | } 83 | 84 | PSL.msg(p, PSL.ADMIN_LASTLOGONS_FOOTER.msg() 85 | .replace("%count%", "" + playerCounter) 86 | .replace("%checked%", "" + offlinePlayerList.length)); 87 | 88 | return true; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminRecreate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.protection.managers.RegionManager; 19 | import com.sk89q.worldguard.protection.managers.RemovalStrategy; 20 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 21 | import dev.espi.protectionstones.*; 22 | import dev.espi.protectionstones.utils.WGUtils; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.ChatColor; 25 | import org.bukkit.World; 26 | import org.bukkit.command.CommandSender; 27 | 28 | import java.util.ArrayList; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | 32 | class ArgAdminRecreate { 33 | static boolean argumentAdminRecreate(CommandSender s, String[] args) { 34 | s.sendMessage(ChatColor.YELLOW + "Recreating..."); 35 | 36 | HashMap m = WGUtils.getAllRegionManagers(); 37 | for (World w : m.keySet()) { 38 | RegionManager rgm = m.get(w); 39 | 40 | List toAdd = new ArrayList<>(); 41 | 42 | for (ProtectedRegion r : rgm.getRegions().values()) { 43 | if (ProtectionStones.isPSRegion(r)) { 44 | PSRegion wr = PSRegion.fromWGRegion(w, r); 45 | if (wr instanceof PSGroupRegion) continue; // skip group regions for now TODO 46 | PSProtectBlock blockOptions = wr.getTypeOptions(); 47 | 48 | if (blockOptions == null) { 49 | Bukkit.getLogger().info("Region " + r.getId() + " in world " + w.getName() + " is not configured in the block config! Skipping..."); 50 | continue; 51 | } 52 | 53 | ProtectedRegion nr = WGUtils.getDefaultProtectedRegion(blockOptions, WGUtils.parsePSRegionToLocation(wr.getId())); 54 | nr.copyFrom(r); // copy region data over 55 | toAdd.add(nr); 56 | } 57 | } 58 | 59 | for (ProtectedRegion r : toAdd) { 60 | rgm.removeRegion(r.getId(), RemovalStrategy.UNSET_PARENT_IN_CHILDREN); 61 | rgm.addRegion(r); 62 | } 63 | } 64 | 65 | s.sendMessage(ChatColor.YELLOW + "Done."); 66 | return true; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminSetTaxAutopayers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.commands; 19 | 20 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 21 | import dev.espi.protectionstones.PSL; 22 | import dev.espi.protectionstones.PSRegion; 23 | import dev.espi.protectionstones.ProtectionStones; 24 | import dev.espi.protectionstones.utils.WGUtils; 25 | import org.bukkit.Bukkit; 26 | import org.bukkit.ChatColor; 27 | import org.bukkit.command.CommandSender; 28 | 29 | class ArgAdminSetTaxAutopayers { 30 | static boolean argumentAdminSetTaxAutopayers(CommandSender s, String[] args) { 31 | if (!ProtectionStones.getInstance().getConfigOptions().taxEnabled) { 32 | return PSL.msg(s, ChatColor.RED + "Taxes are disabled! Enable it in the config."); 33 | } 34 | 35 | PSL.msg(s, ChatColor.GRAY + "Scanning through regions, and setting tax autopayers for regions that don't have one..."); 36 | 37 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 38 | WGUtils.getAllRegionManagers().forEach((w, rgm) -> { 39 | for (ProtectedRegion r : rgm.getRegions().values()) { 40 | PSRegion psr = PSRegion.fromWGRegion(w, r); 41 | 42 | if (psr != null && psr.getTypeOptions() != null && psr.getTypeOptions().taxPeriod != -1 && psr.getTaxAutopayer() == null) { 43 | if (psr.getOwners().size() >= 1) { 44 | PSL.msg(s, ChatColor.GRAY + "Configured tax autopayer to be " + psr.getOwners().get(0).toString() + " for region " + psr.getId()); 45 | psr.setTaxAutopayer(psr.getOwners().get(0)); 46 | } 47 | } 48 | 49 | } 50 | }); 51 | PSL.msg(s, ChatColor.GREEN + "Complete!"); 52 | }); 53 | 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgAdminStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import com.sk89q.worldguard.protection.managers.RegionManager; 20 | import dev.espi.protectionstones.ProtectionStones; 21 | import dev.espi.protectionstones.utils.WGUtils; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.OfflinePlayer; 25 | import org.bukkit.World; 26 | import org.bukkit.command.CommandSender; 27 | 28 | import java.util.HashMap; 29 | 30 | class ArgAdminStats { 31 | 32 | // /ps admin stats 33 | static boolean argumentAdminStats(CommandSender p, String[] args) { 34 | WorldGuardPlugin wg = WorldGuardPlugin.inst(); 35 | 36 | int size = 0; 37 | for (RegionManager rgm : WGUtils.getAllRegionManagers().values()) { 38 | size += rgm.getRegions().values().stream().filter(ProtectionStones::isPSRegion).count(); 39 | } 40 | 41 | if (args.length > 2) { 42 | String playerName = args[2]; 43 | OfflinePlayer op = Bukkit.getOfflinePlayer(playerName); 44 | int count = 0; 45 | HashMap m = WGUtils.getAllRegionManagers(); 46 | for (RegionManager rgm : m.values()) { 47 | count += rgm.getRegionCountOfPlayer(wg.wrapOfflinePlayer(op)); 48 | } 49 | p.sendMessage(ChatColor.YELLOW + playerName + ":"); 50 | p.sendMessage(ChatColor.YELLOW + "================"); 51 | long firstPlayed = (System.currentTimeMillis() - op.getFirstPlayed()) / 86400000L; 52 | p.sendMessage(ChatColor.YELLOW + "First played " + firstPlayed + " days ago."); 53 | long lastPlayed = (System.currentTimeMillis() - op.getLastPlayed()) / 86400000L; 54 | p.sendMessage(ChatColor.YELLOW + "Last played " + lastPlayed + " days ago."); 55 | 56 | String banMessage = (op.isBanned()) ? "Banned" : "Not Banned"; 57 | p.sendMessage(ChatColor.YELLOW + banMessage); 58 | p.sendMessage(ChatColor.YELLOW + "Regions: " + count); 59 | p.sendMessage(ChatColor.YELLOW + "================"); 60 | return true; 61 | } 62 | 63 | p.sendMessage(ChatColor.YELLOW + "================"); 64 | p.sendMessage(ChatColor.YELLOW + "Regions: " + size); 65 | p.sendMessage(ChatColor.YELLOW + "================"); 66 | 67 | return true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgBuySell.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.PSPlayer; 20 | import dev.espi.protectionstones.PSRegion; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import dev.espi.protectionstones.utils.LimitUtil; 23 | import dev.espi.protectionstones.utils.UUIDCache; 24 | import org.apache.commons.lang3.math.NumberUtils; 25 | import org.bukkit.Bukkit; 26 | import org.bukkit.ChatColor; 27 | import org.bukkit.command.CommandSender; 28 | import org.bukkit.entity.Player; 29 | 30 | import java.text.DecimalFormat; 31 | import java.util.Arrays; 32 | import java.util.HashMap; 33 | import java.util.List; 34 | 35 | public class ArgBuySell implements PSCommandArg { 36 | @Override 37 | public List getNames() { 38 | return Arrays.asList("buy", "sell"); 39 | } 40 | 41 | @Override 42 | public boolean allowNonPlayersToExecute() { 43 | return false; 44 | } 45 | 46 | @Override 47 | public List getPermissionsToExecute() { 48 | return Arrays.asList("protectionstones.buysell"); 49 | } 50 | 51 | @Override 52 | public HashMap getRegisteredFlags() { 53 | return null; 54 | } 55 | 56 | @Override 57 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 58 | Player p = (Player) s; 59 | if (!p.hasPermission("protectionstones.buysell")) { 60 | PSL.msg(p, PSL.NO_PERMISSION_BUYSELL.msg()); 61 | return true; 62 | } 63 | 64 | if (!ProtectionStones.getInstance().isVaultSupportEnabled()) { 65 | Bukkit.getLogger().info(ChatColor.RED + "Vault is required, but is not enabled on this server. Contact an administrator."); 66 | s.sendMessage(ChatColor.RED + "Vault is required, but is not enabled on this server. Contact an administrator."); 67 | return true; 68 | } 69 | 70 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 71 | if (r == null) 72 | return PSL.msg(p, PSL.NOT_IN_REGION.msg()); 73 | 74 | if (args[0].equals("buy")) { // buying 75 | 76 | if (!r.forSale()) 77 | return PSL.msg(p, PSL.BUY_NOT_FOR_SALE.msg()); 78 | 79 | if ((!r.getTypeOptions().permission.equals("") && !p.hasPermission(r.getTypeOptions().permission))) 80 | return PSL.msg(p, PSL.NO_PERMISSION_REGION_TYPE.msg()); 81 | 82 | // check if player reached region limit 83 | if (!LimitUtil.check(p, r.getTypeOptions())) 84 | return PSL.msg(p, PSL.REACHED_REGION_LIMIT.msg().replace("%limit%", "" + PSPlayer.fromPlayer(p).getGlobalRegionLimits())); 85 | 86 | if (!PSPlayer.fromPlayer(p).hasAmount(r.getPrice())) 87 | return PSL.msg(p, PSL.NOT_ENOUGH_MONEY.msg().replace("%price%", new DecimalFormat("#.##").format(r.getPrice()))); 88 | 89 | PSL.msg(p, PSL.BUY_SOLD_BUYER.msg() 90 | .replace("%region%", r.getName() == null ? r.getId() : r.getName()) 91 | .replace("%price%", String.format("%.2f", r.getPrice())) 92 | .replace("%player%", UUIDCache.getNameFromUUID(r.getLandlord()))); 93 | 94 | if (Bukkit.getPlayer(r.getLandlord()) != null) { 95 | PSL.msg(Bukkit.getPlayer(r.getLandlord()), PSL.BUY_SOLD_SELLER.msg() 96 | .replace("%region%", r.getName() == null ? r.getId() : r.getName()) 97 | .replace("%price%", String.format("%.2f", r.getPrice())) 98 | .replace("%player%", p.getName())); 99 | } 100 | 101 | r.sell(p.getUniqueId()); 102 | 103 | } else if (args[0].equals("sell")) { // selling 104 | 105 | if (!r.isOwner(p.getUniqueId())) 106 | return PSL.msg(p, PSL.NOT_OWNER.msg()); 107 | 108 | if (args.length != 2) 109 | return PSL.msg(p, PSL.SELL_HELP.msg()); 110 | 111 | if (r.getRentStage() != PSRegion.RentStage.NOT_RENTING) 112 | return PSL.msg(p, PSL.SELL_RENTED_OUT.msg()); 113 | 114 | if (args[1].equals("stop")) { 115 | r.setSellable(false, null, 0); 116 | PSL.msg(p, PSL.BUY_STOP_SELL.msg()); 117 | } else { 118 | if (!NumberUtils.isNumber(args[1])) 119 | return PSL.msg(p, PSL.SELL_HELP.msg()); 120 | 121 | PSL.msg(p, PSL.SELL_FOR_SALE.msg().replace("%price%", String.format("%.2f", Double.parseDouble(args[1])))); 122 | r.setSellable(true, p.getUniqueId(), Double.parseDouble(args[1])); 123 | } 124 | } 125 | 126 | return true; 127 | } 128 | 129 | @Override 130 | public List tabComplete(CommandSender sender, String alias, String[] args) { 131 | return null; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgCount.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSGroupRegion; 19 | import dev.espi.protectionstones.PSL; 20 | import dev.espi.protectionstones.PSPlayer; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import dev.espi.protectionstones.utils.UUIDCache; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.World; 25 | import org.bukkit.command.CommandSender; 26 | import org.bukkit.entity.Player; 27 | 28 | import java.util.*; 29 | 30 | public class ArgCount implements PSCommandArg { 31 | 32 | // Only PS regions, not other regions 33 | static int[] countRegionsOfPlayer(UUID uuid, World w) { 34 | int[] count = {0, 0}; // total, including merged 35 | 36 | PSPlayer psp = PSPlayer.fromUUID(uuid); 37 | psp.getPSRegions(w, false).forEach(r -> { 38 | count[0]++; 39 | if (r instanceof PSGroupRegion) { 40 | count[1] += ((PSGroupRegion) r).getMergedRegions().size(); 41 | } 42 | }); 43 | 44 | return count; 45 | } 46 | 47 | @Override 48 | public List getNames() { 49 | return Collections.singletonList("count"); 50 | } 51 | 52 | @Override 53 | public boolean allowNonPlayersToExecute() { 54 | return false; 55 | } 56 | 57 | @Override 58 | public List getPermissionsToExecute() { 59 | return Arrays.asList("protectionstones.count", "protectionstones.count.others"); 60 | } 61 | 62 | @Override 63 | public HashMap getRegisteredFlags() { 64 | return null; 65 | } 66 | 67 | // /ps count 68 | @Override 69 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 70 | Player p = (Player) s; 71 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 72 | int[] count; 73 | 74 | if (args.length == 1) { 75 | if (!p.hasPermission("protectionstones.count")) { 76 | PSL.msg(p, PSL.NO_PERMISSION_COUNT.msg()); 77 | return; 78 | } 79 | 80 | count = countRegionsOfPlayer(p.getUniqueId(), p.getWorld()); 81 | PSL.msg(p, PSL.PERSONAL_REGION_COUNT.msg().replace("%num%", "" + count[0])); 82 | if (count[1] != 0) { 83 | PSL.msg(p, PSL.PERSONAL_REGION_COUNT_MERGED.msg().replace("%num%", ""+count[1])); 84 | } 85 | 86 | } else if (args.length == 2) { 87 | 88 | if (!p.hasPermission("protectionstones.count.others")) { 89 | PSL.msg(p, PSL.NO_PERMISSION_COUNT_OTHERS.msg()); 90 | return; 91 | } 92 | if (!UUIDCache.containsName(args[1])) { 93 | PSL.msg(p, PSL.PLAYER_NOT_FOUND.msg()); 94 | return; 95 | } 96 | 97 | UUID countUuid = UUIDCache.getUUIDFromName(args[1]); 98 | count = countRegionsOfPlayer(countUuid, p.getWorld()); 99 | 100 | PSL.msg(p, PSL.OTHER_REGION_COUNT.msg() 101 | .replace("%player%", UUIDCache.getNameFromUUID(countUuid)) 102 | .replace("%num%", "" + count[0])); 103 | if (count[1] != 0) { 104 | PSL.msg(p, PSL.OTHER_REGION_COUNT_MERGED.msg() 105 | .replace("%player%", UUIDCache.getNameFromUUID(countUuid)) 106 | .replace("%num%", "" + count[1])); 107 | } 108 | } else { 109 | PSL.msg(p, PSL.COUNT_HELP.msg()); 110 | } 111 | }); 112 | return true; 113 | } 114 | 115 | @Override 116 | public List tabComplete(CommandSender sender, String alias, String[] args) { 117 | return null; 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgGet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSPlayer; 19 | import dev.espi.protectionstones.PSProtectBlock; 20 | import dev.espi.protectionstones.PSL; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import net.md_5.bungee.api.chat.ClickEvent; 23 | import net.md_5.bungee.api.chat.ComponentBuilder; 24 | import net.md_5.bungee.api.chat.HoverEvent; 25 | import net.md_5.bungee.api.chat.TextComponent; 26 | import net.milkbowl.vault.economy.EconomyResponse; 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.command.CommandSender; 29 | import org.bukkit.entity.Player; 30 | import org.bukkit.util.StringUtil; 31 | 32 | import java.text.DecimalFormat; 33 | import java.util.*; 34 | 35 | public class ArgGet implements PSCommandArg { 36 | 37 | @Override 38 | public List getNames() { 39 | return Collections.singletonList("get"); 40 | } 41 | 42 | @Override 43 | public boolean allowNonPlayersToExecute() { 44 | return false; 45 | } 46 | 47 | @Override 48 | public List getPermissionsToExecute() { 49 | return Collections.singletonList("protectionstones.get"); 50 | } 51 | 52 | @Override 53 | public HashMap getRegisteredFlags() { 54 | return null; 55 | } 56 | 57 | private boolean openGetGUI(Player p) { 58 | PSL.msg(p, PSL.GET_HEADER.msg()); 59 | for (PSProtectBlock b : ProtectionStones.getInstance().getConfiguredBlocks()) { 60 | if ((!b.permission.equals("") && !p.hasPermission(b.permission)) || (b.preventPsGet && !p.hasPermission("protectionstones.admin"))) { 61 | continue; // no permission 62 | } 63 | 64 | String price = new DecimalFormat("#.##").format(b.price); 65 | 66 | TextComponent tc = new TextComponent(PSL.GET_GUI_BLOCK.msg() 67 | .replace("%alias%", b.alias) 68 | .replace("%price%", price) 69 | .replace("%description%", b.description) 70 | .replace("%xradius%", ""+b.xRadius) 71 | .replace("%yradius%", ""+b.yRadius) 72 | .replace("%zradius%", ""+b.zRadius)); 73 | 74 | tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(PSL.GET_GUI_HOVER.msg() 75 | .replace("%alias%", b.alias) 76 | .replace("%price%", price) 77 | .replace("%description%", b.description) 78 | .replace("%xradius%", ""+b.xRadius) 79 | .replace("%yradius%", ""+b.yRadius) 80 | .replace("%zradius%", ""+b.zRadius)).create())); 81 | tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " get " + b.alias)); 82 | 83 | p.spigot().sendMessage(tc); 84 | } 85 | return true; 86 | } 87 | 88 | @Override 89 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 90 | Player p = (Player) s; 91 | PSPlayer psp = PSPlayer.fromPlayer(p); 92 | if (!p.hasPermission("protectionstones.get")) 93 | return PSL.msg(p, PSL.NO_PERMISSION_GET.msg()); 94 | 95 | // /ps get (for GUI) 96 | if (args.length == 1) return openGetGUI(p); 97 | 98 | if (args.length != 2) 99 | return PSL.msg(p, PSL.GET_HELP.msg()); 100 | 101 | // check if argument is valid block 102 | PSProtectBlock cp = ProtectionStones.getProtectBlockFromAlias(args[1]); 103 | if (cp == null) 104 | return PSL.msg(p, PSL.INVALID_BLOCK.msg()); 105 | 106 | // check for block permission (custom) 107 | if (!cp.permission.equals("") && !p.hasPermission(cp.permission)) 108 | return PSL.msg(p, PSL.GET_NO_PERMISSION_BLOCK.msg()); 109 | 110 | // check if /ps get is disabled on this 111 | if (cp.preventPsGet && !p.hasPermission("protectionstones.admin")) 112 | return PSL.msg(p, PSL.GET_NO_PERMISSION_BLOCK.msg()); 113 | 114 | // check if player has enough money 115 | if (ProtectionStones.getInstance().isVaultSupportEnabled() && cp.price != 0 && !psp.hasAmount(cp.price)) 116 | return PSL.msg(p, PSL.NOT_ENOUGH_MONEY.msg().replace("%price%", String.format("%.2f", cp.price))); 117 | 118 | // debug message 119 | if (!ProtectionStones.getInstance().isVaultSupportEnabled() && cp.price != 0) { 120 | Bukkit.getLogger().info("Vault is not enabled but there is a price set on the protection stone! It will not work!"); 121 | } 122 | 123 | // take money 124 | if (ProtectionStones.getInstance().isVaultSupportEnabled() && cp.price != 0) { 125 | EconomyResponse er = psp.withdrawBalance(cp.price); 126 | if (!er.transactionSuccess()) { 127 | return PSL.msg(p, er.errorMessage); 128 | } 129 | } 130 | 131 | // check if item was able to be added (inventory not full) 132 | if (!p.getInventory().addItem(cp.createItem()).isEmpty()) { 133 | if (ProtectionStones.getInstance().getConfigOptions().dropItemWhenInventoryFull) { // drop on floor 134 | PSL.msg(p, PSL.NO_ROOM_DROPPING_ON_FLOOR.msg()); 135 | p.getWorld().dropItem(p.getLocation(), cp.createItem()); 136 | } else { // cancel event 137 | PSL.msg(p, PSL.NO_ROOM_IN_INVENTORY.msg()); 138 | if (ProtectionStones.getInstance().isVaultSupportEnabled()) { 139 | EconomyResponse er = psp.depositBalance(cp.price); 140 | if (!er.transactionSuccess()) { 141 | return PSL.msg(p, er.errorMessage); 142 | } 143 | } 144 | } 145 | return true; 146 | } 147 | 148 | return PSL.msg(p, PSL.GET_GOTTEN.msg()); 149 | } 150 | 151 | // tab completion 152 | @Override 153 | public List tabComplete(CommandSender sender, String alias, String[] args) { 154 | List l = new ArrayList<>(); 155 | for (PSProtectBlock b : ProtectionStones.getInstance().getConfiguredBlocks()) { 156 | if ((!b.permission.equals("") && !sender.hasPermission(b.permission)) || (b.preventPsGet && !sender.hasPermission("protectionstones.admin"))) continue; // no permission 157 | l.add(b.alias); 158 | } 159 | return args.length == 2 ? StringUtil.copyPartialMatches(args[1], l, new ArrayList<>()) : null; 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgGive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSProtectBlock; 19 | import dev.espi.protectionstones.PSL; 20 | import dev.espi.protectionstones.ProtectionStones; 21 | import org.apache.commons.lang3.math.NumberUtils; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.command.CommandSender; 24 | import org.bukkit.entity.Player; 25 | import org.bukkit.inventory.ItemStack; 26 | import org.bukkit.util.StringUtil; 27 | 28 | import java.util.*; 29 | 30 | public class ArgGive implements PSCommandArg { 31 | 32 | @Override 33 | public List getNames() { 34 | return Collections.singletonList("give"); 35 | } 36 | 37 | @Override 38 | public boolean allowNonPlayersToExecute() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public List getPermissionsToExecute() { 44 | return Collections.singletonList("protectionstones.give"); 45 | } 46 | 47 | @Override 48 | public HashMap getRegisteredFlags() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public boolean executeArgument(CommandSender p, String[] args, HashMap flags) { 54 | if (!p.hasPermission("protectionstones.give")) 55 | return PSL.msg(p, PSL.NO_PERMISSION_GIVE.msg()); 56 | 57 | if (args.length < 3) 58 | return PSL.msg(p, PSL.GIVE_HELP.msg()); 59 | 60 | // check if player online 61 | if (Bukkit.getPlayer(args[2]) == null) 62 | return PSL.msg(p, PSL.PLAYER_NOT_FOUND.msg() + " (" + args[2] + ")"); 63 | 64 | // check if argument is valid block 65 | PSProtectBlock cp = ProtectionStones.getProtectBlockFromAlias(args[1]); 66 | if (cp == null) 67 | return PSL.msg(p, PSL.INVALID_BLOCK.msg()); 68 | 69 | // check if item was able to be added (inventory not full) 70 | Player ps = Bukkit.getPlayer(args[2]); 71 | 72 | ItemStack item = cp.createItem(); 73 | if (args.length >= 4 && NumberUtils.isNumber(args[3])) 74 | item.setAmount(Integer.parseInt(args[3])); 75 | 76 | if (!ps.getInventory().addItem(item).isEmpty()) { 77 | if (ProtectionStones.getInstance().getConfigOptions().dropItemWhenInventoryFull) { 78 | PSL.msg(ps, PSL.NO_ROOM_DROPPING_ON_FLOOR.msg()); 79 | ps.getWorld().dropItem(ps.getLocation(), cp.createItem()); 80 | } else { 81 | return PSL.msg(p, PSL.GIVE_NO_INVENTORY_ROOM.msg()); 82 | } 83 | } 84 | 85 | return PSL.msg(p, PSL.GIVE_GIVEN.msg().replace("%block%", args[1]).replace("%player%", Bukkit.getPlayer(args[2]).getDisplayName())); 86 | } 87 | 88 | // tab completion 89 | @Override 90 | public List tabComplete(CommandSender sender, String alias, String[] args) { 91 | List l = new ArrayList<>(); 92 | if (args.length == 2) { 93 | for (PSProtectBlock b : ProtectionStones.getInstance().getConfiguredBlocks()) l.add(b.alias); 94 | return StringUtil.copyPartialMatches(args[1], l, new ArrayList<>()); 95 | } else if (args.length == 3) { 96 | for (Player p : Bukkit.getOnlinePlayers()) l.add(p.getName()); 97 | return StringUtil.copyPartialMatches(args[2], l, new ArrayList<>()); 98 | } 99 | return null; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgHelp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.ProtectionStones; 20 | import dev.espi.protectionstones.utils.MiscUtil; 21 | import dev.espi.protectionstones.utils.TextGUI; 22 | import net.md_5.bungee.api.chat.ClickEvent; 23 | import net.md_5.bungee.api.chat.ComponentBuilder; 24 | import net.md_5.bungee.api.chat.HoverEvent; 25 | import net.md_5.bungee.api.chat.TextComponent; 26 | import org.apache.commons.lang3.StringUtils; 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.ChatColor; 29 | import org.bukkit.command.CommandSender; 30 | 31 | import java.util.ArrayList; 32 | import java.util.Collections; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | 36 | public class ArgHelp implements PSCommandArg { 37 | 38 | private static class HelpEntry { 39 | String[] permission; 40 | TextComponent msg; 41 | 42 | HelpEntry(TextComponent msg, String... permission) { 43 | this.permission = permission; 44 | this.msg = msg; 45 | } 46 | } 47 | 48 | public static List helpMenu = new ArrayList<>(); 49 | 50 | public static void initHelpMenu() { 51 | String base = "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " "; 52 | 53 | helpMenu.clear(); 54 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.INFO_HELP.msg(), PSL.INFO_HELP_DESC.msg(), base + "info"), "protectionstones.info")); 55 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.ADDREMOVE_HELP.msg(), PSL.ADDREMOVE_HELP_DESC.msg(), base), "protectionstones.members")); 56 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.ADDREMOVE_OWNER_HELP.msg(), PSL.ADDREMOVE_OWNER_HELP_DESC.msg(), base), "protectionstones.owners")); 57 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.GET_HELP.msg(), PSL.GET_HELP_DESC.msg(), base + "get"), "protectionstones.get")); 58 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.GIVE_HELP.msg(), PSL.GIVE_HELP_DESC.msg(), base + "give"), "protectionstones.give")); 59 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.COUNT_HELP.msg(), PSL.COUNT_HELP_DESC.msg(), base + "count"), "protectionstones.count", "protectionstones.count.others")); 60 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.LIST_HELP.msg(), PSL.LIST_HELP_DESC.msg(), base + "list"), "protectionstones.list", "protectionstones.list.others")); 61 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.NAME_HELP.msg(), PSL.NAME_HELP_DESC.msg(), base + "name"), "protectionstones.name")); 62 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.MERGE_HELP.msg(), PSL.MERGE_HELP_DESC.msg(), base + "merge"), "protectionstones.merge")); 63 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.SETPARENT_HELP.msg(), PSL.SETPARENT_HELP_DESC.msg(), base + "setparent"), "protectionstones.setparent", "protectionstones.setparent.others")); 64 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.FLAG_HELP.msg(), PSL.FLAG_HELP_DESC.msg(), base + "flag"), "protectionstones.flags")); 65 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.RENT_HELP.msg(), PSL.RENT_HELP_DESC.msg(), base + "rent"), "protectionstones.rent")); 66 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.TAX_HELP.msg(), PSL.TAX_HELP_DESC.msg(), base + "tax"), "protectionstones.tax")); 67 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.BUY_HELP.msg(), PSL.BUY_HELP_DESC.msg(), base + "buy"), "protectionstones.buysell")); 68 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.SELL_HELP.msg(), PSL.SELL_HELP_DESC.msg(), base + "sell"), "protectionstones.buysell")); 69 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.HOME_HELP.msg(), PSL.HOME_HELP_DESC.msg(), base + "home"), "protectionstones.home")); 70 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.SETHOME_HELP.msg(), PSL.SETHOME_HELP_DESC.msg(), base + "sethome"), "protectionstones.sethome")); 71 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.TP_HELP.msg(), PSL.TP_HELP_DESC.msg(), base + "tp"), "protectionstones.tp")); 72 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.VISIBILITY_HIDE_HELP.msg(), PSL.VISIBILITY_HIDE_HELP_DESC.msg(), base + "hide"), "protectionstones.hide")); 73 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.VISIBILITY_UNHIDE_HELP.msg(), PSL.VISIBILITY_UNHIDE_HELP_DESC.msg(), base + "unhide"), "protectionstones.unhide")); 74 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.TOGGLE_HELP.msg(), PSL.TOGGLE_HELP_DESC.msg(), base + "toggle"), "protectionstones.toggle")); 75 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.VIEW_HELP.msg(), PSL.VIEW_HELP_DESC.msg(), base + "view"), "protectionstones.view")); 76 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.UNCLAIM_HELP.msg(), PSL.UNCLAIM_HELP_DESC.msg(), base + "unclaim"), "protectionstones.unclaim")); 77 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.PRIORITY_HELP.msg(), PSL.PRIORITY_HELP_DESC.msg(), base + "priority"), "protectionstones.priority")); 78 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.REGION_HELP.msg(), PSL.REGION_HELP_DESC.msg(), base + "region"), "protectionstones.region")); 79 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.ADMIN_HELP.msg(), PSL.ADMIN_HELP_DESC.msg(), base + "admin"), "protectionstones.admin")); 80 | helpMenu.add(new HelpEntry(sendWithPerm(PSL.RELOAD_HELP.msg(), PSL.RELOAD_HELP_DESC.msg(), base + "reload"), "protectionstones.admin")); 81 | } 82 | 83 | @Override 84 | public List getNames() { 85 | return Collections.singletonList("help"); 86 | } 87 | 88 | @Override 89 | public boolean allowNonPlayersToExecute() { 90 | return false; 91 | } 92 | 93 | @Override 94 | public List getPermissionsToExecute() { 95 | return null; 96 | } 97 | 98 | @Override 99 | public HashMap getRegisteredFlags() { 100 | return null; 101 | } 102 | 103 | private static final int GUI_SIZE = 16; 104 | 105 | @Override 106 | public boolean executeArgument(CommandSender p, String[] args, HashMap flags) { 107 | int page = 0; 108 | if (args.length > 1 && MiscUtil.isValidInteger(args[1])) { 109 | page = Integer.parseInt(args[1]) - 1; 110 | } 111 | 112 | List entries = new ArrayList<>(); 113 | for (HelpEntry he : helpMenu) { 114 | // ignore blank lines 115 | if (he.msg.getText().equals("")) { 116 | continue; 117 | } 118 | // check player permissions 119 | for (String perm : he.permission) { 120 | if (p.hasPermission(perm)) { 121 | entries.add(he.msg); 122 | break; 123 | } 124 | } 125 | } 126 | 127 | TextGUI.displayGUI(p, PSL.HELP.msg(), "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " help %page%", page, GUI_SIZE, entries, false); 128 | 129 | if (page >= 0 && page * GUI_SIZE + GUI_SIZE < entries.size()) { 130 | PSL.msg(p, PSL.HELP_NEXT.msg().replace("%page%", page + 2 + "")); 131 | } 132 | 133 | return true; 134 | } 135 | 136 | @Override 137 | public List tabComplete(CommandSender sender, String alias, String[] args) { 138 | return null; 139 | } 140 | 141 | private static TextComponent sendWithPerm(String msg, String desc, String cmd) { 142 | TextComponent m = new TextComponent(msg); 143 | m.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, cmd)); 144 | m.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(desc).create())); 145 | return m; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgHideUnhide.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.*; 20 | import dev.espi.protectionstones.utils.WGUtils; 21 | import org.bukkit.command.CommandSender; 22 | import org.bukkit.entity.Player; 23 | 24 | import java.util.Arrays; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | 28 | public class ArgHideUnhide implements PSCommandArg { 29 | 30 | @Override 31 | public List getNames() { 32 | return Arrays.asList("hide", "unhide"); 33 | } 34 | 35 | @Override 36 | public boolean allowNonPlayersToExecute() { 37 | return false; 38 | } 39 | 40 | @Override 41 | public List getPermissionsToExecute() { 42 | return Arrays.asList("protectionstones.hide", "protectionstones.unhide"); 43 | } 44 | 45 | @Override 46 | public HashMap getRegisteredFlags() { 47 | return null; 48 | } 49 | 50 | @Override 51 | public boolean executeArgument(CommandSender s, String[] arg, HashMap flags) { 52 | Player p = (Player) s; 53 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 54 | 55 | // preliminary checks 56 | if (arg[0].equals("unhide") && !p.hasPermission("protectionstones.unhide")) 57 | return PSL.msg(p, PSL.NO_PERMISSION_UNHIDE.msg()); 58 | 59 | if (arg[0].equals("hide") && !p.hasPermission("protectionstones.hide")) 60 | return PSL.msg(p, PSL.NO_PERMISSION_HIDE.msg()); 61 | 62 | if (r == null) 63 | return PSL.msg(p, PSL.NOT_IN_REGION.msg()); 64 | 65 | if (WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), false)) 66 | return PSL.msg(p, PSL.NO_ACCESS.msg()); 67 | 68 | if (r.isHidden()) { 69 | if (arg[0].equals("hide")) { 70 | return PSL.msg(p, PSL.ALREADY_HIDDEN.msg()); 71 | } 72 | r.unhide(); 73 | } else { 74 | if (arg[0].equals("unhide")) { 75 | return PSL.msg(p, PSL.ALREADY_NOT_HIDDEN.msg()); 76 | } 77 | r.hide(); 78 | } 79 | return true; 80 | } 81 | 82 | @Override 83 | public List tabComplete(CommandSender sender, String alias, String[] args) { 84 | return null; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgHome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.*; 19 | import dev.espi.protectionstones.utils.ChatUtil; 20 | import dev.espi.protectionstones.utils.MiscUtil; 21 | import dev.espi.protectionstones.utils.TextGUI; 22 | import net.md_5.bungee.api.chat.ClickEvent; 23 | import net.md_5.bungee.api.chat.ComponentBuilder; 24 | import net.md_5.bungee.api.chat.HoverEvent; 25 | import net.md_5.bungee.api.chat.TextComponent; 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.ChatColor; 28 | import org.bukkit.command.CommandSender; 29 | import org.bukkit.entity.Player; 30 | import org.bukkit.util.StringUtil; 31 | 32 | import java.util.*; 33 | import java.util.stream.Collectors; 34 | 35 | public class ArgHome implements PSCommandArg { 36 | 37 | private static HashMap> tabCache = new HashMap<>(); 38 | 39 | @Override 40 | public List getNames() { 41 | return Collections.singletonList("home"); 42 | } 43 | 44 | @Override 45 | public boolean allowNonPlayersToExecute() { 46 | return false; 47 | } 48 | 49 | @Override 50 | public List getPermissionsToExecute() { 51 | return Arrays.asList("protectionstones.home"); 52 | } 53 | 54 | @Override 55 | public HashMap getRegisteredFlags() { 56 | HashMap h = new HashMap<>(); 57 | h.put("-p", true); 58 | return h; 59 | } 60 | 61 | // tab completion 62 | @Override 63 | public List tabComplete(CommandSender sender, String alias, String[] args) { 64 | if (!(sender instanceof Player p)) return null; 65 | PSPlayer psp = PSPlayer.fromPlayer(p); 66 | 67 | if (args.length == 2) { 68 | 69 | // add to cache if not already 70 | if (tabCache.get(p.getUniqueId()) == null) { 71 | List regions = psp.getHomes(p.getWorld()); 72 | List regionNames = new ArrayList<>(); 73 | for (PSRegion r : regions) { 74 | if (r.getName() != null) { 75 | regionNames.add(r.getName()); 76 | } else { 77 | regionNames.add(r.getId()); 78 | } 79 | } 80 | // cache home regions 81 | tabCache.put(p.getUniqueId(), regionNames); 82 | 83 | Bukkit.getScheduler().runTaskLater(ProtectionStones.getInstance(), () -> { 84 | tabCache.remove(p.getUniqueId()); 85 | }, 200); // remove cache after 10 seconds 86 | } 87 | 88 | return StringUtil.copyPartialMatches(args[1], tabCache.get(p.getUniqueId()), new ArrayList<>()); 89 | } 90 | return null; 91 | } 92 | 93 | private static final int GUI_SIZE = 17; 94 | 95 | private void openHomeGUI(PSPlayer psp, List homes, int page) { 96 | List entries = new ArrayList<>(); 97 | for (PSRegion r : homes) { 98 | String msg; 99 | if (r.getName() == null) { 100 | msg = ChatColor.GRAY + "> " + ChatColor.AQUA + r.getId(); 101 | } else { 102 | msg = ChatColor.GRAY + "> " + ChatColor.AQUA + r.getName() + " (" + r.getId() + ")"; 103 | } 104 | TextComponent tc = new TextComponent(msg); 105 | tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(PSL.HOME_CLICK_TO_TP.msg()).create())); 106 | if (r.getName() == null) { 107 | tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " home " + r.getId())); 108 | } else { 109 | tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " home " + r.getName())); 110 | } 111 | entries.add(tc); 112 | } 113 | 114 | TextGUI.displayGUI(psp.getPlayer(), PSL.HOME_HEADER.msg(), "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " home -p %page%", page, GUI_SIZE, entries, true); 115 | 116 | if (page * GUI_SIZE + GUI_SIZE < entries.size()) 117 | PSL.msg(psp, PSL.HOME_NEXT.msg().replace("%page%", page + 2 + "")); 118 | } 119 | 120 | @Override 121 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 122 | Player p = (Player) s; 123 | 124 | // prelim checks 125 | if (!p.hasPermission("protectionstones.home")) 126 | return PSL.msg(p, PSL.NO_PERMISSION_HOME.msg()); 127 | 128 | if (args.length != 2 && args.length != 1) 129 | return PSL.msg(p, PSL.HOME_HELP.msg()); 130 | 131 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 132 | PSPlayer psp = PSPlayer.fromPlayer(p); 133 | if (args.length == 1) { 134 | // just "/ps home" 135 | List regions = psp.getHomes(p.getWorld()); 136 | if (regions.size() == 1) { // teleport to home if there is only one home 137 | ArgTp.teleportPlayer(p, regions.get(0)); 138 | } else { // otherwise, open the GUI 139 | openHomeGUI(psp, regions, (flags.get("-p") == null || !MiscUtil.isValidInteger(flags.get("-p")) ? 0 : Integer.parseInt(flags.get("-p")) - 1)); 140 | } 141 | } else {// /ps home [id] 142 | // get regions from the query 143 | String query = args[1]; 144 | List regions = psp.getHomes(p.getWorld()) 145 | .stream() 146 | .filter(region -> region.getId().equals(query) 147 | || (region.getName() != null && region.getName().equals(query))) 148 | .collect(Collectors.toList()); 149 | 150 | if (regions.isEmpty()) { 151 | PSL.msg(s, PSL.REGION_DOES_NOT_EXIST.msg()); 152 | return; 153 | } 154 | 155 | // if there is more than one name in the query 156 | if (regions.size() > 1) { 157 | ChatUtil.displayDuplicateRegionAliases(p, regions); 158 | return; 159 | } 160 | 161 | ArgTp.teleportPlayer(p, regions.get(0)); 162 | } 163 | }); 164 | 165 | return true; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.PSPlayer; 20 | import dev.espi.protectionstones.PSRegion; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import dev.espi.protectionstones.utils.UUIDCache; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.ChatColor; 25 | import org.bukkit.command.CommandSender; 26 | import org.bukkit.entity.HumanEntity; 27 | import org.bukkit.entity.Player; 28 | import org.bukkit.util.StringUtil; 29 | 30 | import java.util.*; 31 | import java.util.stream.Collectors; 32 | 33 | public class ArgList implements PSCommandArg { 34 | @Override 35 | public List getNames() { 36 | return Collections.singletonList("list"); 37 | } 38 | 39 | @Override 40 | public boolean allowNonPlayersToExecute() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public List getPermissionsToExecute() { 46 | return Arrays.asList("protectionstones.list"); 47 | } 48 | 49 | @Override 50 | public HashMap getRegisteredFlags() { 51 | return null; 52 | } 53 | 54 | @Override 55 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 56 | if (!s.hasPermission("protectionstones.list")) 57 | return PSL.msg(s, PSL.NO_PERMISSION_LIST.msg()); 58 | 59 | if (args.length == 2 && !s.hasPermission("protectionstones.list.others")) 60 | return PSL.msg(s, PSL.NO_PERMISSION_LIST_OTHERS.msg()); 61 | 62 | if (args.length == 2 && !UUIDCache.containsName(args[1])) 63 | return PSL.msg(s, PSL.PLAYER_NOT_FOUND.msg()); 64 | 65 | PSPlayer psp = PSPlayer.fromPlayer((Player) s); 66 | 67 | // run query async to reduce load 68 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 69 | if (args.length == 1) { 70 | List regions = psp.getPSRegionsCrossWorld(psp.getPlayer().getWorld(), true); 71 | display(s, regions, psp.getUuid(), true); 72 | } else if (args.length == 2) { 73 | UUID uuid = UUIDCache.getUUIDFromName(args[1]); 74 | List regions = PSPlayer.fromUUID(uuid).getPSRegionsCrossWorld(psp.getPlayer().getWorld(), true); 75 | display(s, regions, uuid, false); 76 | } else { 77 | PSL.msg(s, PSL.LIST_HELP.msg()); 78 | } 79 | }); 80 | return true; 81 | } 82 | 83 | @Override 84 | public List tabComplete(CommandSender sender, String alias, String[] args) { 85 | if (!sender.hasPermission("protectionstones.list") || !sender.hasPermission("protectionstones.list.others")) { 86 | return null; 87 | } 88 | if (args.length == 2) { 89 | // autocomplete with online player list 90 | return StringUtil.copyPartialMatches(args[1], Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList()), new ArrayList<>()); 91 | } 92 | 93 | return null; 94 | } 95 | 96 | private void display(CommandSender s, List regions, UUID pUUID, boolean isCurrentPlayer) { 97 | List ownerOf = new ArrayList<>(), memberOf = new ArrayList<>(); 98 | for (PSRegion r : regions) { 99 | if (r.isOwner(pUUID)) { 100 | if (r.getName() == null) { 101 | ownerOf.add(ChatColor.GRAY + "> " + ChatColor.AQUA + r.getId()); 102 | } else { 103 | ownerOf.add(ChatColor.GRAY + "> " + ChatColor.AQUA + r.getName() + " (" + r.getId() + ")"); 104 | } 105 | } 106 | if (r.isMember(pUUID)) { 107 | if (r.getName() == null) { 108 | memberOf.add(ChatColor.GRAY + "> " + ChatColor.AQUA + r.getId()); 109 | } else { 110 | memberOf.add(ChatColor.GRAY + "> " + ChatColor.AQUA + r.getName() + " (" + r.getId() + ")"); 111 | } 112 | } 113 | } 114 | 115 | if (ownerOf.isEmpty() && memberOf.isEmpty()) { 116 | if (isCurrentPlayer) { 117 | PSL.msg(s, PSL.LIST_NO_REGIONS.msg()); 118 | } else { 119 | PSL.msg(s, PSL.LIST_NO_REGIONS_PLAYER.msg().replace("%player%", UUIDCache.getNameFromUUID(pUUID))); 120 | } 121 | return; 122 | } 123 | 124 | PSL.msg(s, PSL.LIST_HEADER.msg().replace("%player%", UUIDCache.getNameFromUUID(pUUID))); 125 | 126 | if (!ownerOf.isEmpty()) { 127 | PSL.msg(s, PSL.LIST_OWNER.msg()); 128 | for (String str : ownerOf) s.sendMessage(str); 129 | } 130 | if (!memberOf.isEmpty()) { 131 | PSL.msg(s, PSL.LIST_MEMBER.msg()); 132 | for (String str : memberOf) s.sendMessage(str); 133 | } 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgMerge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.LocalPlayer; 19 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 20 | import com.sk89q.worldguard.protection.managers.RegionManager; 21 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 22 | import dev.espi.protectionstones.*; 23 | import dev.espi.protectionstones.utils.WGMerge; 24 | import dev.espi.protectionstones.utils.WGUtils; 25 | import net.md_5.bungee.api.chat.ClickEvent; 26 | import net.md_5.bungee.api.chat.ComponentBuilder; 27 | import net.md_5.bungee.api.chat.HoverEvent; 28 | import net.md_5.bungee.api.chat.TextComponent; 29 | import org.bukkit.Bukkit; 30 | import org.bukkit.ChatColor; 31 | import org.bukkit.command.CommandSender; 32 | import org.bukkit.entity.Player; 33 | 34 | import java.util.*; 35 | import java.util.stream.Collectors; 36 | 37 | public class ArgMerge implements PSCommandArg { 38 | @Override 39 | public List getNames() { 40 | return Arrays.asList("merge"); 41 | } 42 | 43 | @Override 44 | public boolean allowNonPlayersToExecute() { 45 | return false; 46 | } 47 | 48 | @Override 49 | public List getPermissionsToExecute() { 50 | return Arrays.asList("protectionstones.merge"); 51 | } 52 | 53 | @Override 54 | public HashMap getRegisteredFlags() { 55 | return null; 56 | } 57 | 58 | public static List getGUI(Player p, PSRegion r) { 59 | return r.getMergeableRegions(p).stream() 60 | .map(psr -> { 61 | TextComponent tc = new TextComponent(ChatColor.AQUA + "> " + ChatColor.WHITE + psr.getId()); 62 | if (psr.getName() != null) tc.addExtra(" (" + psr.getName() + ")"); // name 63 | tc.addExtra(" (" + psr.getTypeOptions().alias + ")"); // region type 64 | 65 | tc.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " merge " + r.getId() + " " + psr.getId())); 66 | tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(PSL.MERGE_CLICK_TO_MERGE.msg().replace("%region%", psr.getId())).create())); 67 | return tc; 68 | }) 69 | .collect(Collectors.toList()); 70 | } 71 | 72 | @Override 73 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 74 | if (!s.hasPermission("protectionstones.merge")) 75 | return PSL.msg(s, PSL.NO_PERMISSION_MERGE.msg()); 76 | 77 | if (!ProtectionStones.getInstance().getConfigOptions().allowMergingRegions) 78 | return PSL.msg(s, PSL.MERGE_DISABLED.msg()); 79 | 80 | Player p = (Player) s; 81 | if (args.length == 1) { // GUI 82 | 83 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 84 | if (r == null) 85 | return PSL.msg(s, PSL.NOT_IN_REGION.msg()); 86 | 87 | if (r.getTypeOptions() == null) { 88 | PSL.msg(p, ChatColor.RED + "This region is problematic, and the block type (" + r.getType() + ") is not configured. Please contact an administrator."); 89 | Bukkit.getLogger().info(ChatColor.RED + "This region is problematic, and the block type (" + r.getType() + ") is not configured."); 90 | return true; 91 | } 92 | 93 | if (!r.getTypeOptions().allowMerging) 94 | return PSL.msg(s, PSL.MERGE_NOT_ALLOWED.msg()); 95 | 96 | List components = getGUI(p, r); 97 | if (components.isEmpty()) { 98 | PSL.msg(p, PSL.MERGE_NO_REGIONS.msg()); 99 | } else { 100 | p.sendMessage(ChatColor.WHITE + ""); // send empty line 101 | PSL.msg(p, PSL.MERGE_HEADER.msg().replace("%region%", r.getId())); 102 | PSL.msg(p, PSL.MERGE_WARNING.msg()); 103 | for (TextComponent tc : components) p.spigot().sendMessage(tc); 104 | p.sendMessage(ChatColor.WHITE + ""); // send empty line 105 | } 106 | 107 | } else if (args.length == 3) { // /ps merge [region] [root] 108 | RegionManager rm = WGUtils.getRegionManagerWithPlayer(p); 109 | ProtectedRegion region = rm.getRegion(args[1]), root = rm.getRegion(args[2]); 110 | LocalPlayer lp = WorldGuardPlugin.inst().wrapPlayer(p); 111 | 112 | if (!ProtectionStones.isPSRegion(region) || !ProtectionStones.isPSRegion(root)) 113 | return PSL.msg(p, PSL.MULTI_REGION_DOES_NOT_EXIST.msg()); 114 | 115 | if (!p.hasPermission("protectionstones.admin") && (!region.isOwner(lp) || !root.isOwner(lp))) 116 | return PSL.msg(p, PSL.NO_ACCESS.msg()); 117 | 118 | // check if region is actually overlapping the region 119 | var overlappingRegionIds = WGUtils.findOverlapOrAdjacentRegions(root, rm, p.getWorld()).stream().map(ProtectedRegion::getId).collect(Collectors.toList()); 120 | if (!overlappingRegionIds.contains(region.getId())) 121 | return PSL.msg(p, PSL.REGION_NOT_OVERLAPPING.msg()); 122 | 123 | // check if merging is allowed in config 124 | PSRegion aRegion = PSRegion.fromWGRegion(p.getWorld(), region), aRoot = PSRegion.fromWGRegion(p.getWorld(), root); 125 | if (!aRegion.getTypeOptions().allowMerging || !aRoot.getTypeOptions().allowMerging) 126 | return PSL.msg(p, PSL.MERGE_NOT_ALLOWED.msg()); 127 | 128 | // check if the region types allow for it 129 | if (!WGUtils.canMergeRegionTypes(aRegion.getTypeOptions(), aRoot)) 130 | return PSL.msg(p, PSL.MERGE_NOT_ALLOWED.msg()); 131 | 132 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 133 | try { 134 | WGMerge.mergeRealRegions(p.getWorld(), rm, aRoot, Arrays.asList(aRegion, aRoot)); 135 | } catch (WGMerge.RegionHoleException e) { 136 | PSL.msg(p, PSL.NO_REGION_HOLES.msg()); 137 | return; 138 | } catch (WGMerge.RegionCannotMergeWhileRentedException e) { 139 | PSL.msg(p, PSL.CANNOT_MERGE_RENTED_REGION.msg().replace("%region%", e.getRentedRegion().getName() == null ? e.getRentedRegion().getId() : e.getRentedRegion().getName())); 140 | return; 141 | } 142 | PSL.msg(p, PSL.MERGE_MERGED.msg()); 143 | 144 | // show menu again if the new region still has overlapping regions 145 | Bukkit.getScheduler().runTask(ProtectionStones.getInstance(), () -> { 146 | if (!getGUI(p, PSRegion.fromWGRegion(p.getWorld(), rm.getRegion(aRoot.getId()))).isEmpty()) { 147 | Bukkit.dispatchCommand(p, ProtectionStones.getInstance().getConfigOptions().base_command + " merge"); 148 | } 149 | }); 150 | }); 151 | 152 | } else { 153 | PSL.msg(s, PSL.MERGE_HELP.msg()); 154 | } 155 | 156 | return true; 157 | } 158 | 159 | @Override 160 | public List tabComplete(CommandSender sender, String alias, String[] args) { 161 | return null; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.PSL; 20 | import dev.espi.protectionstones.PSRegion; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import dev.espi.protectionstones.utils.WGUtils; 23 | import org.bukkit.command.CommandSender; 24 | import org.bukkit.entity.Player; 25 | 26 | import java.util.Arrays; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | 31 | public class ArgName implements PSCommandArg { 32 | @Override 33 | public List getNames() { 34 | return Collections.singletonList("name"); 35 | } 36 | 37 | @Override 38 | public boolean allowNonPlayersToExecute() { 39 | return false; 40 | } 41 | 42 | @Override 43 | public List getPermissionsToExecute() { 44 | return Arrays.asList("protectionstones.name"); 45 | } 46 | 47 | @Override 48 | public HashMap getRegisteredFlags() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 54 | if (!s.hasPermission("protectionstones.name")) { 55 | PSL.msg(s, PSL.NO_PERMISSION_NAME.msg()); 56 | return true; 57 | } 58 | Player p = (Player) s; 59 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 60 | if (r == null) { 61 | PSL.msg(s, PSL.NOT_IN_REGION.msg()); 62 | return true; 63 | } 64 | if (WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), false)) { 65 | PSL.msg(s, PSL.NO_ACCESS.msg()); 66 | return true; 67 | } 68 | if (args.length < 2) { 69 | PSL.msg(s, PSL.NAME_HELP.msg()); 70 | return true; 71 | } 72 | 73 | if (args[1].equals("none")) { 74 | r.setName(null); 75 | PSL.msg(p, PSL.NAME_REMOVED.msg().replace("%id%", r.getId())); 76 | } else { 77 | if (!ProtectionStones.getInstance().getConfigOptions().allowDuplicateRegionNames && ProtectionStones.isPSNameAlreadyUsed(args[1])) { 78 | PSL.msg(p, PSL.NAME_TAKEN.msg().replace("%name%", args[1])); 79 | return true; 80 | } 81 | r.setName(args[1]); 82 | PSL.msg(p, PSL.NAME_SET_NAME.msg().replace("%id%", r.getId()).replace("%name%", r.getName())); 83 | } 84 | return true; 85 | } 86 | 87 | @Override 88 | public List tabComplete(CommandSender sender, String alias, String[] args) { 89 | return null; 90 | } 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgPriority.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.PSL; 20 | import dev.espi.protectionstones.PSRegion; 21 | import dev.espi.protectionstones.utils.WGUtils; 22 | import org.bukkit.command.CommandSender; 23 | import org.bukkit.entity.Player; 24 | 25 | import java.util.Arrays; 26 | import java.util.Collections; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | 30 | public class ArgPriority implements PSCommandArg { 31 | 32 | @Override 33 | public List getNames() { 34 | return Collections.singletonList("priority"); 35 | } 36 | 37 | @Override 38 | public boolean allowNonPlayersToExecute() { 39 | return false; 40 | } 41 | 42 | @Override 43 | public List getPermissionsToExecute() { 44 | return Arrays.asList("protectionstones.priority"); 45 | } 46 | 47 | @Override 48 | public HashMap getRegisteredFlags() { 49 | return null; 50 | } 51 | 52 | @Override 53 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 54 | Player p = (Player) s; 55 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 56 | 57 | if (!p.hasPermission("protectionstones.priority")) { 58 | PSL.msg(p, PSL.NO_PERMISSION_PRIORITY.msg()); 59 | return true; 60 | } 61 | if (r == null) { 62 | PSL.msg(p, PSL.NOT_IN_REGION.msg()); 63 | return true; 64 | } 65 | if (WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), false)) { 66 | PSL.msg(p, PSL.NO_ACCESS.msg()); 67 | return true; 68 | } 69 | if (args.length < 2) { 70 | int priority = r.getWGRegion().getPriority(); 71 | PSL.msg(p, PSL.PRIORITY_INFO.msg().replace("%priority%", "" + priority)); 72 | return true; 73 | } 74 | 75 | try { 76 | int priority = Integer.parseInt(args[1]); 77 | r.getWGRegion().setPriority(priority); 78 | PSL.msg(p, PSL.PRIORITY_SET.msg()); 79 | } catch (NumberFormatException e) { 80 | PSL.msg(p, PSL.PRIORITY_ERROR.msg()); 81 | } 82 | return true; 83 | } 84 | 85 | @Override 86 | public List tabComplete(CommandSender sender, String alias, String[] args) { 87 | return null; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.protection.managers.RegionManager; 19 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 20 | import dev.espi.protectionstones.PSL; 21 | import dev.espi.protectionstones.PSRegion; 22 | import dev.espi.protectionstones.ProtectionStones; 23 | import dev.espi.protectionstones.utils.UUIDCache; 24 | import dev.espi.protectionstones.utils.WGUtils; 25 | import org.bukkit.command.CommandSender; 26 | import org.bukkit.entity.Player; 27 | import org.bukkit.util.StringUtil; 28 | 29 | import java.util.*; 30 | 31 | public class ArgRegion implements PSCommandArg { 32 | 33 | // /ps region 34 | 35 | @Override 36 | public List getNames() { 37 | return Collections.singletonList("region"); 38 | } 39 | 40 | @Override 41 | public boolean allowNonPlayersToExecute() { 42 | return false; 43 | } 44 | 45 | @Override 46 | public List getPermissionsToExecute() { 47 | return Arrays.asList("protectionstones.region"); 48 | } 49 | 50 | @Override 51 | public HashMap getRegisteredFlags() { 52 | return null; 53 | } 54 | 55 | @Override 56 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 57 | Player p = (Player) s; 58 | RegionManager rgm = WGUtils.getRegionManagerWithPlayer(p); 59 | 60 | if (!p.hasPermission("protectionstones.region")) { 61 | PSL.msg(p, PSL.NO_PERMISSION_REGION.msg()); 62 | return true; 63 | } 64 | 65 | if (args.length < 3) { 66 | PSL.msg(p, PSL.REGION_HELP.msg()); 67 | return true; 68 | } 69 | 70 | if (!UUIDCache.containsName(args[2])) { 71 | PSL.msg(p, PSL.PLAYER_NOT_FOUND.msg()); 72 | return true; 73 | } 74 | 75 | UUID playerUuid = UUIDCache.getUUIDFromName(args[2]); 76 | 77 | if (args[1].equalsIgnoreCase("list")) { // list player's regions 78 | StringBuilder regionMessage = new StringBuilder(); 79 | boolean found = false; 80 | for (ProtectedRegion r : rgm.getRegions().values()) { 81 | if (ProtectionStones.isPSRegion(r) && r.getOwners().contains(playerUuid)) { 82 | found = true; 83 | regionMessage.append(r.getId()).append(", "); 84 | } 85 | } 86 | 87 | if (!found) { 88 | PSL.msg(p, PSL.REGION_NOT_FOUND_FOR_PLAYER.msg() 89 | .replace("%player%", args[2])); 90 | } else { 91 | regionMessage = new StringBuilder(regionMessage.substring(0, regionMessage.length() - 2) + "."); 92 | PSL.msg(p, PSL.REGION_LIST.msg() 93 | .replace("%player%", args[2]) 94 | .replace("%regions%", regionMessage)); 95 | } 96 | 97 | } else if ((args[1].equalsIgnoreCase("remove")) || (args[1].equalsIgnoreCase("disown"))) { 98 | 99 | boolean found = false; 100 | for (ProtectedRegion r : rgm.getRegions().values()) { 101 | if (ProtectionStones.isPSRegion(r)) { 102 | 103 | PSRegion psr = PSRegion.fromWGRegion(p.getWorld(), r); 104 | if (psr.isOwner(playerUuid)) { 105 | found = true; 106 | 107 | // remove as owner 108 | psr.removeOwner(playerUuid); 109 | 110 | // remove region if empty and is "remove" mode 111 | if (psr.getOwners().size() == 0 && args[1].equalsIgnoreCase("remove")) { 112 | psr.deleteRegion(true); 113 | } 114 | } 115 | } 116 | } 117 | 118 | if (!found) { 119 | PSL.msg(p, PSL.REGION_NOT_FOUND_FOR_PLAYER.msg().replace("%player%", args[2])); 120 | return true; 121 | } 122 | 123 | if (args[1].equalsIgnoreCase("remove")) { 124 | PSL.msg(p, PSL.REGION_REMOVE.msg().replace("%player%", args[2])); 125 | } else if (args[1].equalsIgnoreCase("disown")) { 126 | PSL.msg(p, PSL.REGION_DISOWN.msg().replace("%player%", args[2])); 127 | } 128 | } else { 129 | PSL.msg(p, PSL.REGION_HELP.msg()); 130 | } 131 | return true; 132 | } 133 | 134 | @Override 135 | public List tabComplete(CommandSender sender, String alias, String[] args) { 136 | return args.length == 2 ? StringUtil.copyPartialMatches(args[1], Arrays.asList("disown", "remove", "list"), new ArrayList<>()) : null; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgReload.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.ProtectionStones; 20 | import org.bukkit.command.CommandSender; 21 | 22 | import java.util.Arrays; 23 | import java.util.Collections; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | 27 | public class ArgReload implements PSCommandArg { 28 | 29 | // /ps reload 30 | 31 | @Override 32 | public List getNames() { 33 | return Collections.singletonList("reload"); 34 | } 35 | 36 | @Override 37 | public boolean allowNonPlayersToExecute() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public List getPermissionsToExecute() { 43 | return Arrays.asList("protectionstones.admin"); 44 | } 45 | 46 | @Override 47 | public HashMap getRegisteredFlags() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public boolean executeArgument(CommandSender p, String[] args, HashMap flags) { 53 | if (!p.hasPermission("protectionstones.admin")) { 54 | PSL.msg(p, PSL.NO_PERMISSION_ADMIN.msg()); 55 | return true; 56 | } 57 | PSL.msg(p, PSL.RELOAD_START.msg()); 58 | ProtectionStones.loadConfig(true); 59 | PSL.msg(p, PSL.RELOAD_COMPLETE.msg()); 60 | return true; 61 | } 62 | 63 | @Override 64 | public List tabComplete(CommandSender sender, String alias, String[] args) { 65 | return null; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgSethome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.PSL; 20 | import dev.espi.protectionstones.PSRegion; 21 | import dev.espi.protectionstones.utils.WGUtils; 22 | import org.bukkit.Location; 23 | import org.bukkit.command.CommandSender; 24 | import org.bukkit.entity.Player; 25 | 26 | import java.util.Arrays; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | 31 | public class ArgSethome implements PSCommandArg { 32 | 33 | // /ps sethome 34 | 35 | @Override 36 | public List getNames() { 37 | return Collections.singletonList("sethome"); 38 | } 39 | 40 | @Override 41 | public boolean allowNonPlayersToExecute() { 42 | return false; 43 | } 44 | 45 | @Override 46 | public List getPermissionsToExecute() { 47 | return Arrays.asList("protectionstones.sethome"); 48 | } 49 | 50 | @Override 51 | public HashMap getRegisteredFlags() { 52 | return null; 53 | } 54 | 55 | @Override 56 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 57 | Player p = (Player) s; 58 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 59 | 60 | WorldGuardPlugin wg = WorldGuardPlugin.inst(); 61 | if (!p.hasPermission("protectionstones.sethome")) 62 | return PSL.msg(p, PSL.NO_PERMISSION_SETHOME.msg()); 63 | 64 | if (r == null) 65 | return PSL.msg(p, PSL.NOT_IN_REGION.msg()); 66 | 67 | if (WGUtils.hasNoAccess(r.getWGRegion(), p, wg.wrapPlayer(p), false)) 68 | return PSL.msg(p, PSL.NO_ACCESS.msg()); 69 | 70 | Location l = p.getLocation(); 71 | r.setHome(l.getBlockX(), l.getBlockY(), l.getBlockZ(), l.getYaw(), l.getPitch()); 72 | return PSL.msg(p, PSL.SETHOME_SET.msg().replace("%psid%", r.getName() != null ? String.format("%s (%s)", r.getName(), r.getId()) : r.getId())); 73 | } 74 | 75 | @Override 76 | public List tabComplete(CommandSender sender, String alias, String[] args) { 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgSetparent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 20 | import dev.espi.protectionstones.PSL; 21 | import dev.espi.protectionstones.PSRegion; 22 | import dev.espi.protectionstones.ProtectionStones; 23 | import dev.espi.protectionstones.utils.ChatUtil; 24 | import dev.espi.protectionstones.utils.WGUtils; 25 | import org.bukkit.command.CommandSender; 26 | import org.bukkit.entity.Player; 27 | 28 | import java.util.Arrays; 29 | import java.util.Collections; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | 33 | public class ArgSetparent implements PSCommandArg { 34 | @Override 35 | public List getNames() { 36 | return Collections.singletonList("setparent"); 37 | } 38 | 39 | @Override 40 | public boolean allowNonPlayersToExecute() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public List getPermissionsToExecute() { 46 | return Arrays.asList("protectionstones.setparent"); 47 | } 48 | 49 | @Override 50 | public HashMap getRegisteredFlags() { 51 | return null; 52 | } 53 | 54 | @Override 55 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 56 | if (!s.hasPermission("protectionstones.setparent")) { 57 | PSL.msg(s, PSL.NO_PERMISSION_SETPARENT.msg()); 58 | return true; 59 | } 60 | Player p = (Player) s; 61 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 62 | if (r == null) { 63 | PSL.msg(s, PSL.NOT_IN_REGION.msg()); 64 | return true; 65 | } 66 | if (WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), false)) { 67 | PSL.msg(s, PSL.NO_ACCESS.msg()); 68 | return true; 69 | } 70 | if (args.length != 2) { 71 | PSL.msg(s, PSL.SETPARENT_HELP.msg()); 72 | return true; 73 | } 74 | 75 | if (args[1].equals("none")) { // remove parent 76 | try { 77 | r.setParent(null); 78 | PSL.msg(s, PSL.SETPARENT_SUCCESS_REMOVE.msg().replace("%id%", r.getName() == null ? r.getId() : r.getName())); 79 | } catch (ProtectedRegion.CircularInheritanceException e) { 80 | e.printStackTrace(); // won't happen ever 81 | } 82 | } else { 83 | List parent = ProtectionStones.getPSRegions(p.getWorld(), args[1]); 84 | 85 | if (parent.isEmpty()) { 86 | PSL.msg(s, PSL.REGION_DOES_NOT_EXIST.msg()); 87 | return true; 88 | } 89 | if (!p.hasPermission("protectionstones.setparent.others") && !parent.get(0).isOwner(p.getUniqueId())) { 90 | PSL.msg(s, PSL.NO_PERMISSION_SETPARENT_OTHERS.msg()); 91 | return true; 92 | } 93 | if (parent.size() > 1) { 94 | ChatUtil.displayDuplicateRegionAliases(p, parent); 95 | return true; 96 | } 97 | 98 | try { 99 | r.setParent(parent.get(0)); 100 | } catch (ProtectedRegion.CircularInheritanceException e) { 101 | PSL.msg(s, PSL.SETPARENT_CIRCULAR_INHERITANCE.msg()); 102 | return true; 103 | } 104 | 105 | PSL.msg(s, PSL.SETPARENT_SUCCESS.msg().replace("%id%", r.getName() == null ? r.getId() : r.getName()) 106 | .replace("%parent%", parent.get(0).getName() == null ? parent.get(0).getId() : parent.get(0).getName())); 107 | } 108 | return false; 109 | } 110 | 111 | @Override 112 | public List tabComplete(CommandSender sender, String alias, String[] args) { 113 | return null; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgToggle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.ProtectionStones; 20 | import org.bukkit.command.CommandSender; 21 | import org.bukkit.entity.Player; 22 | 23 | import java.util.Arrays; 24 | import java.util.Collections; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | 28 | public class ArgToggle implements PSCommandArg { 29 | 30 | // /ps on 31 | public static class ArgToggleOn implements PSCommandArg { 32 | @Override 33 | public List getNames() { 34 | return Collections.singletonList("on"); 35 | } 36 | @Override 37 | public boolean allowNonPlayersToExecute() { 38 | return false; 39 | } 40 | @Override 41 | public List getPermissionsToExecute() { 42 | return Collections.singletonList("protectionstones.toggle"); 43 | } 44 | @Override 45 | public HashMap getRegisteredFlags() { 46 | return null; 47 | } 48 | @Override 49 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 50 | Player p = (Player) s; 51 | if (p.hasPermission("protectionstones.toggle")) { 52 | ProtectionStones.toggleList.remove(p.getUniqueId()); 53 | p.sendMessage(PSL.TOGGLE_ON.msg()); 54 | } else { 55 | p.sendMessage(PSL.NO_PERMISSION_TOGGLE.msg()); 56 | } 57 | return true; 58 | } 59 | @Override 60 | public List tabComplete(CommandSender sender, String alias, String[] args) { 61 | return null; 62 | } 63 | } 64 | 65 | // /ps off 66 | public static class ArgToggleOff implements PSCommandArg { 67 | @Override 68 | public List getNames() { 69 | return Collections.singletonList("off"); 70 | } 71 | @Override 72 | public boolean allowNonPlayersToExecute() { 73 | return false; 74 | } 75 | @Override 76 | public List getPermissionsToExecute() { 77 | return Collections.singletonList("protectionstones.toggle"); 78 | } 79 | @Override 80 | public HashMap getRegisteredFlags() { 81 | return null; 82 | } 83 | @Override 84 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 85 | Player p = (Player) s; 86 | if (p.hasPermission("protectionstones.toggle")) { 87 | ProtectionStones.toggleList.add(p.getUniqueId()); 88 | p.sendMessage(PSL.TOGGLE_OFF.msg()); 89 | } else { 90 | p.sendMessage(PSL.NO_PERMISSION_TOGGLE.msg()); 91 | } 92 | return true; 93 | } 94 | @Override 95 | public List tabComplete(CommandSender sender, String alias, String[] args) { 96 | return null; 97 | } 98 | } 99 | 100 | @Override 101 | public List getNames() { 102 | return Collections.singletonList("toggle"); 103 | } 104 | 105 | @Override 106 | public boolean allowNonPlayersToExecute() { 107 | return false; 108 | } 109 | 110 | @Override 111 | public List getPermissionsToExecute() { 112 | return Collections.singletonList("protectionstones.toggle"); 113 | } 114 | 115 | @Override 116 | public HashMap getRegisteredFlags() { 117 | return null; 118 | } 119 | 120 | @Override 121 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 122 | Player p = (Player) s; 123 | if (p.hasPermission("protectionstones.toggle")) { 124 | if (!ProtectionStones.toggleList.contains(p.getUniqueId())) { 125 | ProtectionStones.toggleList.add(p.getUniqueId()); 126 | p.sendMessage(PSL.TOGGLE_OFF.msg()); 127 | } else { 128 | ProtectionStones.toggleList.remove(p.getUniqueId()); 129 | p.sendMessage(PSL.TOGGLE_ON.msg()); 130 | } 131 | } else { 132 | p.sendMessage(PSL.NO_PERMISSION_TOGGLE.msg()); 133 | } 134 | return true; 135 | } 136 | 137 | @Override 138 | public List tabComplete(CommandSender sender, String alias, String[] args) { 139 | return null; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgUnclaim.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import dev.espi.protectionstones.*; 19 | import dev.espi.protectionstones.utils.TextGUI; 20 | import net.md_5.bungee.api.chat.ClickEvent; 21 | import net.md_5.bungee.api.chat.ComponentBuilder; 22 | import net.md_5.bungee.api.chat.HoverEvent; 23 | import net.md_5.bungee.api.chat.TextComponent; 24 | import org.bukkit.ChatColor; 25 | import org.bukkit.command.CommandSender; 26 | import org.bukkit.entity.Player; 27 | import org.bukkit.inventory.ItemStack; 28 | 29 | import java.util.ArrayList; 30 | import java.util.Collections; 31 | import java.util.HashMap; 32 | import java.util.List; 33 | 34 | public class ArgUnclaim implements PSCommandArg { 35 | 36 | // /ps unclaim 37 | 38 | @Override 39 | public List getNames() { 40 | return Collections.singletonList("unclaim"); 41 | } 42 | 43 | @Override 44 | public boolean allowNonPlayersToExecute() { 45 | return false; 46 | } 47 | 48 | @Override 49 | public List getPermissionsToExecute() { 50 | return Collections.singletonList("protectionstones.unclaim"); 51 | } 52 | 53 | @Override 54 | public HashMap getRegisteredFlags() { 55 | return null; 56 | } 57 | 58 | @Override 59 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 60 | Player p = (Player) s; 61 | 62 | 63 | if (!p.hasPermission("protectionstones.unclaim")) { 64 | PSL.msg(p, PSL.NO_PERMISSION_UNCLAIM.msg()); 65 | return true; 66 | } 67 | 68 | if (args.length >= 2) { // /ps unclaim [list|region-id] (unclaim remote region) 69 | 70 | if (!p.hasPermission("protectionstones.unclaim.remote")) { 71 | PSL.msg(p, PSL.NO_PERMISSION_UNCLAIM_REMOTE.msg()); 72 | return true; 73 | } 74 | 75 | PSPlayer psp = PSPlayer.fromPlayer(p); 76 | 77 | // list of regions that the player owns 78 | List regions = psp.getPSRegionsCrossWorld(psp.getPlayer().getWorld(), false); 79 | 80 | if (args[1].equalsIgnoreCase("list")) { 81 | displayPSRegions(s, regions, args.length == 2 ? 0 : tryParseInt(args[2]) - 1); 82 | } else { 83 | for (PSRegion psr : regions) { 84 | if (psr.getId().equalsIgnoreCase(args[1])) { 85 | // cannot break region being rented (prevents splitting merged regions, and breaking as tenant owner) 86 | if (psr.getRentStage() == PSRegion.RentStage.RENTING && !p.hasPermission("protectionstones.superowner")) { 87 | PSL.msg(p, PSL.RENT_CANNOT_BREAK_WHILE_RENTING.msg()); 88 | return false; 89 | } 90 | return unclaimBlock(psr, p); 91 | } 92 | } 93 | PSL.msg(p, PSL.REGION_DOES_NOT_EXIST.msg()); 94 | } 95 | 96 | return true; 97 | } else { // /ps unclaim (no arguments, unclaim current region) 98 | PSRegion r = PSRegion.fromLocationGroupUnsafe(p.getLocation()); // allow unclaiming unconfigured regions 99 | 100 | if (r == null) { 101 | PSL.msg(p, PSL.NOT_IN_REGION.msg()); 102 | return true; 103 | } 104 | 105 | if (!r.isOwner(p.getUniqueId()) && !p.hasPermission("protectionstones.superowner")) { 106 | PSL.msg(p, PSL.NO_REGION_PERMISSION.msg()); 107 | return true; 108 | } 109 | 110 | // cannot break region being rented (prevents splitting merged regions, and breaking as tenant owner) 111 | if (r.getRentStage() == PSRegion.RentStage.RENTING && !p.hasPermission("protectionstones.superowner")) { 112 | PSL.msg(p, PSL.RENT_CANNOT_BREAK_WHILE_RENTING.msg()); 113 | return true; 114 | } 115 | return unclaimBlock(r, p); 116 | } 117 | } 118 | 119 | @Override 120 | public List tabComplete(CommandSender sender, String alias, String[] args) { 121 | return null; 122 | } 123 | 124 | private int tryParseInt(String arg) { 125 | int i = 1; 126 | try { 127 | i = Integer.parseInt(arg); 128 | } catch (NumberFormatException ignore) { 129 | //ignore 130 | } 131 | return i; 132 | } 133 | 134 | private void displayPSRegions(CommandSender s, List regions, int page) { 135 | List entries = new ArrayList<>(); 136 | for (PSRegion rs : regions) { 137 | String msg; 138 | if (rs.getName() == null) { 139 | msg = ChatColor.GRAY + "> " + ChatColor.AQUA + rs.getId(); 140 | } else { 141 | msg = ChatColor.GRAY + "> " + ChatColor.AQUA + rs.getName() + " (" + rs.getId() + ")"; 142 | } 143 | TextComponent tc = new TextComponent(ChatColor.AQUA + " [-] " + msg); 144 | tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Click to unclaim " + rs.getId()).create())); 145 | tc.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " unclaim " + rs.getId())); 146 | entries.add(tc); 147 | } 148 | TextGUI.displayGUI(s, PSL.UNCLAIM_HEADER.msg(), "/" + ProtectionStones.getInstance().getConfigOptions().base_command + " unclaim list %page%", page, 17, entries, true); 149 | } 150 | 151 | private boolean unclaimBlock(PSRegion r, Player p) { 152 | PSProtectBlock cpb = r.getTypeOptions(); 153 | if (cpb != null && !cpb.noDrop) { 154 | // return protection stone 155 | List items = new ArrayList<>(); 156 | 157 | if (r instanceof PSGroupRegion) { 158 | for (PSRegion rp : ((PSGroupRegion) r).getMergedRegions()) { 159 | if (rp.getTypeOptions() != null) items.add(rp.getTypeOptions().createItem()); 160 | } 161 | } else { 162 | items.add(cpb.createItem()); 163 | } 164 | 165 | for (ItemStack item : items) { 166 | if (!p.getInventory().addItem(item).isEmpty()) { 167 | // method will return not empty if item couldn't be added 168 | if (ProtectionStones.getInstance().getConfigOptions().dropItemWhenInventoryFull) { 169 | PSL.msg(p, PSL.NO_ROOM_DROPPING_ON_FLOOR.msg()); 170 | p.getWorld().dropItem(p.getLocation(), item); 171 | } else { 172 | PSL.msg(p, PSL.NO_ROOM_IN_INVENTORY.msg()); 173 | return true; 174 | } 175 | } 176 | } 177 | } 178 | // remove region 179 | // check if removing the region and firing region remove event blocked it 180 | if (!r.deleteRegion(true, p)) { 181 | if (!ProtectionStones.getInstance().getConfigOptions().allowMergingHoles) { // side case if the removing creates a hole and those are prevented 182 | PSL.msg(p, PSL.DELETE_REGION_PREVENTED_NO_HOLES.msg()); 183 | } 184 | return true; 185 | } 186 | 187 | PSL.msg(p, PSL.NO_LONGER_PROTECTED.msg()); 188 | 189 | return true; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/ArgView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import com.sk89q.worldguard.bukkit.WorldGuardPlugin; 19 | import dev.espi.protectionstones.*; 20 | import dev.espi.protectionstones.utils.ParticlesUtil; 21 | import dev.espi.protectionstones.utils.RegionTraverse; 22 | import dev.espi.protectionstones.utils.WGUtils; 23 | import org.bukkit.*; 24 | import org.bukkit.command.CommandSender; 25 | import org.bukkit.entity.Player; 26 | 27 | import java.util.*; 28 | import java.util.concurrent.atomic.AtomicInteger; 29 | 30 | public class ArgView implements PSCommandArg { 31 | 32 | private static List cooldown = new ArrayList<>(); 33 | 34 | @Override 35 | public List getNames() { 36 | return Collections.singletonList("view"); 37 | } 38 | 39 | @Override 40 | public boolean allowNonPlayersToExecute() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public List getPermissionsToExecute() { 46 | return Arrays.asList("protectionstones.view"); 47 | } 48 | 49 | @Override 50 | public HashMap getRegisteredFlags() { 51 | return null; 52 | } 53 | 54 | @Override 55 | public boolean executeArgument(CommandSender s, String[] args, HashMap flags) { 56 | Player p = (Player) s; 57 | 58 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 59 | 60 | if (!p.hasPermission("protectionstones.view")) { 61 | PSL.msg(p, PSL.NO_PERMISSION_VIEW.msg()); 62 | return true; 63 | } 64 | if (r == null) { 65 | PSL.msg(p, PSL.NOT_IN_REGION.msg()); 66 | return true; 67 | } 68 | if (!p.hasPermission("protectionstones.view.others") && WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), true)) { 69 | PSL.msg(p, PSL.NO_ACCESS.msg()); 70 | return true; 71 | } 72 | if (cooldown.contains(p.getUniqueId())) { 73 | PSL.msg(p, PSL.VIEW_COOLDOWN.msg()); 74 | return true; 75 | } 76 | 77 | PSL.msg(p, PSL.VIEW_GENERATING.msg()); 78 | 79 | // add player to cooldown 80 | cooldown.add(p.getUniqueId()); 81 | Bukkit.getScheduler().runTaskLaterAsynchronously(ProtectionStones.getInstance(), () -> cooldown.remove(p.getUniqueId()), 20 * ProtectionStones.getInstance().getConfigOptions().psViewCooldown); 82 | 83 | int playerY = p.getLocation().getBlockY(), minY = r.getWGRegion().getMinimumPoint().getBlockY(), maxY = r.getWGRegion().getMaximumPoint().getBlockY(); 84 | 85 | // send particles to client 86 | 87 | Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> { 88 | 89 | AtomicInteger modU = new AtomicInteger(0); 90 | 91 | if (r instanceof PSGroupRegion) { 92 | PSGroupRegion pr = (PSGroupRegion) r; 93 | for (PSMergedRegion psmr : pr.getMergedRegions()) { 94 | handlePurpleParticle(p, new Location(p.getWorld(), 0.5 + psmr.getProtectBlock().getX(), 1.5 + psmr.getProtectBlock().getY(), 0.5 + psmr.getProtectBlock().getZ())); 95 | for (int y = minY; y <= maxY; y += 10) { 96 | handlePurpleParticle(p, new Location(p.getWorld(), 0.5 + psmr.getProtectBlock().getX(), 0.5 + y, 0.5 + psmr.getProtectBlock().getZ())); 97 | } 98 | } 99 | } else { 100 | handlePurpleParticle(p, new Location(p.getWorld(), 0.5 + r.getProtectBlock().getX(), 1.5 + r.getProtectBlock().getY(), 0.5 + r.getProtectBlock().getZ())); 101 | for (int y = minY; y <= maxY; y += 10) { 102 | handlePurpleParticle(p, new Location(p.getWorld(), 0.5 + r.getProtectBlock().getX(), 0.5 + y, 0.5 + r.getProtectBlock().getZ())); 103 | } 104 | } 105 | 106 | RegionTraverse.traverseRegionEdge(new HashSet<>(r.getWGRegion().getPoints()), Collections.singletonList(r.getWGRegion()), tr -> { 107 | if (tr.isVertex) { 108 | handleBlueParticle(p, new Location(p.getWorld(), 0.5+tr.point.getX(), 0.5+playerY, 0.5+tr.point.getZ())); 109 | for (int y = minY; y <= maxY; y += 5) { 110 | handleBlueParticle(p, new Location(p.getWorld(), 0.5+tr.point.getX(), 0.5+y, 0.5+tr.point.getZ())); 111 | } 112 | } else { 113 | if (modU.get() % 2 == 0) { 114 | handlePinkParticle(p, new Location(p.getWorld(), 0.5+tr.point.getX(), 0.5+playerY, 0.5+tr.point.getZ())); 115 | handlePinkParticle(p, new Location(p.getWorld(), 0.5+tr.point.getX(), 0.5+minY, 0.5+tr.point.getZ())); 116 | handlePinkParticle(p, new Location(p.getWorld(), 0.5+tr.point.getX(), 0.5+maxY, 0.5+tr.point.getZ())); 117 | } 118 | modU.set((modU.get() + 1) % 2); 119 | } 120 | }); 121 | }); 122 | return true; 123 | } 124 | 125 | @Override 126 | public List tabComplete(CommandSender sender, String alias, String[] args) { 127 | return null; 128 | } 129 | 130 | private static int PARTICLE_VIEW_DISTANCE_LIMIT = 150; 131 | 132 | private static boolean handlePinkParticle(Player p, Location l) { 133 | if (p.getLocation().distance(l) > PARTICLE_VIEW_DISTANCE_LIMIT || Math.abs(l.getY()-p.getLocation().getY()) > 30) return false; 134 | ParticlesUtil.persistRedstoneParticle(p, l, new Particle.DustOptions(Color.fromRGB(233, 30, 99), 2), 30); 135 | return true; 136 | } 137 | 138 | private static boolean handleBlueParticle(Player p, Location l) { 139 | if (p.getLocation().distance(l) > PARTICLE_VIEW_DISTANCE_LIMIT || Math.abs(l.getY()-p.getLocation().getY()) > 30) return false; 140 | ParticlesUtil.persistRedstoneParticle(p, l, new Particle.DustOptions(Color.fromRGB(0, 255, 255), 2), 30); 141 | return true; 142 | } 143 | 144 | private static boolean handlePurpleParticle(Player p, Location l) { 145 | if (p.getLocation().distance(l) > PARTICLE_VIEW_DISTANCE_LIMIT || Math.abs(l.getY()-p.getLocation().getY()) > 30) return false; 146 | ParticlesUtil.persistRedstoneParticle(p, l, new Particle.DustOptions(Color.fromRGB(255, 0, 255), 10), 30); 147 | return true; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/commands/PSCommandArg.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.commands; 17 | 18 | import org.bukkit.command.CommandSender; 19 | 20 | import java.util.HashMap; 21 | import java.util.List; 22 | 23 | public interface PSCommandArg { 24 | List getNames(); 25 | boolean allowNonPlayersToExecute(); 26 | List getPermissionsToExecute(); 27 | HashMap getRegisteredFlags(); // 28 | boolean executeArgument(CommandSender s, String[] args, HashMap flags); 29 | List tabComplete(CommandSender sender, String alias, String[] args); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/event/PSBreakProtectBlockEvent.java: -------------------------------------------------------------------------------- 1 | package dev.espi.protectionstones.event; 2 | 3 | import dev.espi.protectionstones.PSRegion; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.Cancellable; 6 | import org.bukkit.event.Event; 7 | import org.bukkit.event.HandlerList; 8 | import org.bukkit.inventory.ItemStack; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | import java.util.Objects; 12 | 13 | import static com.google.common.base.Preconditions.checkNotNull; 14 | 15 | /** 16 | * Event that is called when a protection stones block is removed 17 | */ 18 | public class PSBreakProtectBlockEvent extends Event implements Cancellable { 19 | 20 | private static final HandlerList HANDLERS = new HandlerList(); 21 | 22 | private PSRegion region; 23 | private Player player; 24 | private boolean isCancelled = false; 25 | 26 | public PSBreakProtectBlockEvent(PSRegion psr, Player player) { 27 | this.region = checkNotNull(psr); 28 | this.player = player; 29 | } 30 | 31 | /** 32 | * Gets the player who triggered the event. 33 | * 34 | * @return The player. 35 | */ 36 | public Player getPlayer() { 37 | return player; 38 | } 39 | 40 | /** 41 | * Gets the ProtectionStones item associated with the region. 42 | * 43 | * @return The ProtectionStones item. 44 | */ 45 | public ItemStack getPSItem() { 46 | return Objects.requireNonNull(region.getTypeOptions()).createItem(); 47 | } 48 | 49 | /** 50 | * Gets the ProtectionStones region associated with the event. 51 | * 52 | * @return The ProtectionStones region. 53 | */ 54 | public PSRegion getRegion() { 55 | return region; 56 | } 57 | 58 | @Override 59 | public boolean isCancelled() { 60 | return isCancelled; 61 | } 62 | 63 | @Override 64 | public void setCancelled(boolean cancel) { 65 | isCancelled = cancel; 66 | } 67 | 68 | @NotNull 69 | @Override 70 | public HandlerList getHandlers() { 71 | return HANDLERS; 72 | } 73 | 74 | public static HandlerList getHandlerList() { 75 | return HANDLERS; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/event/PSCreateEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.event; 17 | 18 | import dev.espi.protectionstones.PSRegion; 19 | import org.bukkit.entity.Player; 20 | import org.bukkit.event.Cancellable; 21 | import org.bukkit.event.Event; 22 | import org.bukkit.event.HandlerList; 23 | 24 | import static com.google.common.base.Preconditions.checkNotNull; 25 | 26 | /** 27 | * Event that is called when a protectionstones region is created, either by a player, or by the plugin. 28 | */ 29 | 30 | public class PSCreateEvent extends Event implements Cancellable { 31 | private static final HandlerList HANDLERS = new HandlerList(); 32 | 33 | private PSRegion region; 34 | private Player p = null; 35 | private boolean isCancelled = false; 36 | 37 | public PSCreateEvent(PSRegion psr, Player player) { 38 | this.region = checkNotNull(psr); 39 | this.p = player; 40 | } 41 | 42 | public PSCreateEvent(PSRegion psr) { 43 | this.region = checkNotNull(psr); 44 | } 45 | 46 | /** 47 | * Returns the player that created the protection region, if applicable 48 | * @return the player, or null if the region was not created because of a player 49 | */ 50 | public Player getPlayer() { 51 | return p; 52 | } 53 | 54 | /** 55 | * Returns the region being created. 56 | * @return the region being created 57 | */ 58 | public PSRegion getRegion() { 59 | return region; 60 | } 61 | 62 | @Override 63 | public boolean isCancelled() { 64 | return isCancelled; 65 | } 66 | 67 | @Override 68 | public void setCancelled(boolean isCancelled) { 69 | this.isCancelled = isCancelled; 70 | } 71 | 72 | @Override 73 | public HandlerList getHandlers() { 74 | return HANDLERS; 75 | } 76 | 77 | public static HandlerList getHandlerList() { 78 | return HANDLERS; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/event/PSLoseRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.event; 17 | 18 | public class PSLoseRegion { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/event/PSObtainRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.event; 17 | 18 | public class PSObtainRegion { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/event/PSRemoveEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.event; 17 | 18 | import dev.espi.protectionstones.PSRegion; 19 | import org.bukkit.entity.Player; 20 | import org.bukkit.event.Cancellable; 21 | import org.bukkit.event.Event; 22 | import org.bukkit.event.HandlerList; 23 | 24 | import static com.google.common.base.Preconditions.checkNotNull; 25 | 26 | /** 27 | * Event that is called when a protection stones region is removed 28 | */ 29 | 30 | public class PSRemoveEvent extends Event implements Cancellable { 31 | private static final HandlerList HANDLERS = new HandlerList(); 32 | 33 | private PSRegion region; 34 | private Player p = null; 35 | private boolean isCancelled = false; 36 | 37 | public PSRemoveEvent(PSRegion psr, Player player) { 38 | this.region = checkNotNull(psr); 39 | this.p = player; 40 | } 41 | 42 | public PSRemoveEvent(PSRegion psr) { 43 | this.region = checkNotNull(psr); 44 | } 45 | 46 | /** 47 | * Returns the player that removed the protect block, if applicable 48 | * @return the player, or null if the region was not removed because of a player 49 | */ 50 | public Player getPlayer() { 51 | return p; 52 | } 53 | 54 | /** 55 | * Returns the region being removed. 56 | * @return the region being removed 57 | */ 58 | public PSRegion getRegion() { 59 | return region; 60 | } 61 | 62 | @Override 63 | public boolean isCancelled() { 64 | return isCancelled; 65 | } 66 | 67 | @Override 68 | public void setCancelled(boolean isCancelled) { 69 | this.isCancelled = isCancelled; 70 | } 71 | 72 | @Override 73 | public HandlerList getHandlers() { 74 | return HANDLERS; 75 | } 76 | 77 | public static HandlerList getHandlerList() { 78 | return HANDLERS; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/flags/FarewellFlagHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.flags; 17 | 18 | import com.sk89q.worldedit.WorldEdit; 19 | import com.sk89q.worldedit.util.Location; 20 | import com.sk89q.worldguard.LocalPlayer; 21 | import com.sk89q.worldguard.protection.ApplicableRegionSet; 22 | import com.sk89q.worldguard.protection.regions.ProtectedRegion; 23 | import com.sk89q.worldguard.session.MoveType; 24 | import com.sk89q.worldguard.session.Session; 25 | import com.sk89q.worldguard.session.handler.FlagValueChangeHandler; 26 | import com.sk89q.worldguard.session.handler.Handler; 27 | import dev.espi.protectionstones.FlagHandler; 28 | import dev.espi.protectionstones.PSRegion; 29 | import dev.espi.protectionstones.ProtectionStones; 30 | import net.md_5.bungee.api.ChatMessageType; 31 | import net.md_5.bungee.api.chat.TextComponent; 32 | import org.bukkit.Bukkit; 33 | import org.bukkit.ChatColor; 34 | import org.bukkit.entity.Player; 35 | 36 | // farewell-action flag 37 | public class FarewellFlagHandler extends FlagValueChangeHandler { 38 | public static final FarewellFlagHandler.Factory FACTORY = new FarewellFlagHandler.Factory(); 39 | public static class Factory extends Handler.Factory { 40 | @Override 41 | public FarewellFlagHandler create(Session session) { 42 | return new FarewellFlagHandler(session); 43 | } 44 | } 45 | 46 | protected FarewellFlagHandler(Session session) { 47 | super(session, FlagHandler.FAREWELL_ACTION); 48 | } 49 | 50 | @Override 51 | protected void onInitialValue(LocalPlayer localPlayer, ApplicableRegionSet applicableRegionSet, String s) { 52 | 53 | } 54 | 55 | @Override 56 | protected boolean onSetValue(LocalPlayer localPlayer, Location from, Location to, ApplicableRegionSet toSet, String currentValue, String lastValue, MoveType moveType) { 57 | Player p = Bukkit.getPlayer(localPlayer.getUniqueId()); 58 | 59 | // the greeting action flag for the other region should show instead if it is set 60 | for (ProtectedRegion r : toSet.getRegions()) { 61 | if (r.getFlag(FlagHandler.GREET_ACTION) != null) { 62 | return true; 63 | } 64 | } 65 | if (p != null && lastValue != null && !lastValue.equals(currentValue)) { 66 | p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', lastValue))); 67 | } 68 | return true; 69 | } 70 | 71 | @Override 72 | protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) { 73 | Player p = Bukkit.getPlayer(localPlayer.getUniqueId()); 74 | if (p != null && lastValue != null) { 75 | p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', lastValue))); 76 | } 77 | return true; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/flags/GreetingFlagHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.flags; 17 | 18 | import com.sk89q.worldedit.util.Location; 19 | import com.sk89q.worldguard.LocalPlayer; 20 | import com.sk89q.worldguard.protection.ApplicableRegionSet; 21 | import com.sk89q.worldguard.session.MoveType; 22 | import com.sk89q.worldguard.session.Session; 23 | import com.sk89q.worldguard.session.handler.FlagValueChangeHandler; 24 | import com.sk89q.worldguard.session.handler.Handler; 25 | import dev.espi.protectionstones.FlagHandler; 26 | import net.md_5.bungee.api.ChatMessageType; 27 | import net.md_5.bungee.api.chat.TextComponent; 28 | import org.bukkit.Bukkit; 29 | import org.bukkit.ChatColor; 30 | 31 | // greeting-action flag 32 | public class GreetingFlagHandler extends FlagValueChangeHandler { 33 | 34 | public static final Factory FACTORY = new Factory(); 35 | public static class Factory extends Handler.Factory { 36 | @Override 37 | public GreetingFlagHandler create(Session session) { 38 | return new GreetingFlagHandler(session); 39 | } 40 | } 41 | 42 | public GreetingFlagHandler(Session session) { 43 | super(session, FlagHandler.GREET_ACTION); 44 | } 45 | 46 | @Override 47 | protected void onInitialValue(LocalPlayer localPlayer, ApplicableRegionSet applicableRegionSet, String s) { 48 | 49 | } 50 | 51 | @Override 52 | protected boolean onSetValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String currentValue, String lastValue, MoveType moveType) { 53 | if (currentValue != null && !currentValue.equals(lastValue) && Bukkit.getPlayer(localPlayer.getUniqueId()) != null) { 54 | Bukkit.getPlayer(localPlayer.getUniqueId()).spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', currentValue))); 55 | } 56 | return true; 57 | } 58 | 59 | @Override 60 | protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) { 61 | return true; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/gui/GUIScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.gui; 17 | 18 | public class GUIScreen { 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/placeholders/PSPlaceholderExpansion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.placeholders; 19 | 20 | import dev.espi.protectionstones.ProtectionStones; 21 | import me.clip.placeholderapi.expansion.PlaceholderExpansion; 22 | import org.bukkit.entity.Player; 23 | 24 | public class PSPlaceholderExpansion extends PlaceholderExpansion { 25 | 26 | // persist through reloads 27 | @Override 28 | public boolean persist() { 29 | return true; 30 | } 31 | 32 | @Override 33 | public boolean canRegister(){ 34 | return true; 35 | } 36 | 37 | @Override 38 | public String getIdentifier() { 39 | return "protectionstones"; 40 | } 41 | 42 | @Override 43 | public String getAuthor() { 44 | return ProtectionStones.getInstance().getDescription().getAuthors().toString(); 45 | } 46 | 47 | @Override 48 | public String getVersion() { 49 | return ProtectionStones.getInstance().getDescription().getVersion(); 50 | } 51 | 52 | @Override 53 | public String onPlaceholderRequest(Player p, String identifier) { 54 | String[] split = identifier.split("_"); 55 | if (split.length > 0) { 56 | switch (split[0]) { 57 | case "config": 58 | return ConfigPlaceholders.resolveConfig(identifier); 59 | case "currentregion": 60 | return RegionPlaceholders.resolveCurrentRegionPlaceholders(p, identifier); 61 | case "region": 62 | return RegionPlaceholders.resolveSpecifiedRegionPlaceholders(p, identifier); 63 | case "currentplayer": 64 | return PlayerPlaceholders.resolvePlayer(p, identifier); 65 | } 66 | } 67 | 68 | return ""; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/placeholders/PlayerPlaceholders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.placeholders; 19 | 20 | import dev.espi.protectionstones.PSPlayer; 21 | import dev.espi.protectionstones.PSProtectBlock; 22 | import dev.espi.protectionstones.PSRegion; 23 | import dev.espi.protectionstones.ProtectionStones; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.World; 26 | import org.bukkit.entity.Player; 27 | 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.stream.Collectors; 31 | 32 | class PlayerPlaceholders { 33 | 34 | static String resolvePlayer(Player p, String identifier) { 35 | if (p == null) return ""; 36 | PSPlayer psp = PSPlayer.fromPlayer(p); 37 | 38 | if (identifier.equals("currentplayer_global_region_limit")) { 39 | 40 | if (p.hasPermission("protectionstones.admin")) { 41 | return "-1"; 42 | } else { 43 | return psp.getGlobalRegionLimits() + ""; 44 | } 45 | 46 | } else if (identifier.startsWith("currentplayer_region_limit_")) { 47 | 48 | String alias = identifier.substring("currentplayer_region_limit_".length()); 49 | List> l = psp.getRegionLimits() 50 | .entrySet() 51 | .stream() 52 | .filter(e -> e.getKey().alias.equals(alias)) 53 | .collect(Collectors.toList()); 54 | 55 | if (p.hasPermission("protectionstones.admin")) { 56 | return "-1"; 57 | } 58 | 59 | if (!l.isEmpty()) { 60 | return l.get(0).getValue() + ""; 61 | } else { 62 | return psp.getGlobalRegionLimits() + ""; 63 | } 64 | 65 | } else if (identifier.startsWith("currentplayer_total_tax_owed")) { 66 | 67 | double amount = 0; 68 | for (PSRegion psr : psp.getTaxEligibleRegions()) { 69 | for (PSRegion.TaxPayment tp : psr.getTaxPaymentsDue()) { 70 | amount += tp.getAmount(); 71 | } 72 | } 73 | return String.format("%.2f", amount); 74 | 75 | } else if (identifier.startsWith("currentplayer_num_of_accessible_regions_")) { 76 | 77 | String world = identifier.substring("currentplayer_num_of_accessible_regions_".length()); 78 | World w = Bukkit.getWorld(world); 79 | return w == null ? "Invalid world." : "" + psp.getPSRegions(w, true).size(); 80 | 81 | } else if (identifier.startsWith("currentplayer_num_of_accessible_regions")) { 82 | 83 | return "" + Bukkit.getWorlds().stream().mapToInt(w -> psp.getPSRegions(w, true).size()).sum(); 84 | 85 | } else if (identifier.startsWith("currentplayer_num_of_owned_regions_")) { 86 | 87 | String world = identifier.substring("currentplayer_num_of_owned_regions_".length()); 88 | World w = Bukkit.getWorld(world); 89 | return w == null ? "Invalid world." : "" + psp.getPSRegions(w, false).size(); 90 | 91 | } else if (identifier.startsWith("currentplayer_num_of_owned_regions")) { 92 | 93 | return "" + Bukkit.getWorlds().stream().mapToInt(w -> psp.getPSRegions(w, false).size()).sum(); 94 | 95 | } else if (identifier.startsWith("currentplayer_owned_regions_ids_")) { 96 | 97 | World w = Bukkit.getWorld(identifier.substring("currentplayer_owned_regions_ids_".length())); 98 | return w == null ? "Invalid world." : getRegionsString(psp.getPSRegions(w, false), false); 99 | 100 | } else if (identifier.startsWith("currentplayer_accessible_regions_ids_")) { 101 | 102 | World w = Bukkit.getWorld(identifier.substring("currentplayer_accessible_regions_ids_".length())); 103 | return w == null ? "Invalid world." : getRegionsString(psp.getPSRegions(w, true), false); 104 | 105 | } else if (identifier.startsWith("currentplayer_owned_regions_names_")) { 106 | 107 | World w = Bukkit.getWorld(identifier.substring("currentplayer_owned_regions_names_".length())); 108 | return w == null ? "Invalid world." : getRegionsString(psp.getPSRegions(w, false), true); 109 | 110 | } else if (identifier.startsWith("currentplayer_accessible_regions_names_")) { 111 | 112 | World w = Bukkit.getWorld(identifier.substring("currentplayer_accessible_regions_names_".length())); 113 | return w == null ? "Invalid world." : getRegionsString(psp.getPSRegions(w, true), true); 114 | 115 | } else if (identifier.startsWith("currentplayer_protection_placing_enabled")) { 116 | 117 | return ProtectionStones.toggleList.contains(p.getUniqueId()) + ""; 118 | 119 | } 120 | return ""; 121 | } 122 | 123 | private static String getRegionsString(List regions, boolean useNamesIfPossible) { 124 | StringBuilder sb = new StringBuilder(); 125 | for (int i = 0; i < regions.size(); i++) { 126 | 127 | if (useNamesIfPossible && regions.get(i).getName() != null) { 128 | sb.append(regions.get(i).getName()); 129 | } else { 130 | sb.append(regions.get(i).getId()); 131 | } 132 | 133 | if (i < regions.size() - 1) { 134 | sb.append(", "); 135 | } 136 | 137 | } 138 | return sb.toString(); 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/placeholders/RegionPlaceholders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.placeholders; 19 | 20 | import com.sk89q.worldguard.protection.flags.Flag; 21 | import com.sk89q.worldguard.protection.flags.Flags; 22 | import dev.espi.protectionstones.PSRegion; 23 | import dev.espi.protectionstones.ProtectionStones; 24 | import dev.espi.protectionstones.utils.MiscUtil; 25 | import dev.espi.protectionstones.utils.UUIDCache; 26 | import dev.espi.protectionstones.utils.WGUtils; 27 | import org.bukkit.entity.Player; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.stream.Collectors; 32 | 33 | class RegionPlaceholders { 34 | 35 | public static String resolveSpecifiedRegionPlaceholders(Player p, String identifier) { 36 | String[] spl = identifier.split("_"); 37 | if (spl.length > 2) { 38 | String regionIdentifier = spl[1]; 39 | List r; 40 | if (p == null) { 41 | r = new ArrayList<>(); 42 | WGUtils.getAllRegionManagers().forEach((w, rgm) -> r.addAll(ProtectionStones.getPSRegions(w, regionIdentifier))); 43 | } else { 44 | r = ProtectionStones.getPSRegions(p.getWorld(), regionIdentifier); 45 | } 46 | 47 | if (!r.isEmpty()) { 48 | if (spl[2].equals("config")) { 49 | return ConfigPlaceholders.resolveBlockConfig(r.get(0).getTypeOptions(), identifier.substring(("region_" + regionIdentifier + "_config_").length())); 50 | } else { 51 | return resolveRegionPlaceholders(p, r.get(0), identifier.substring(("region_" + regionIdentifier + "_").length())); 52 | } 53 | } 54 | } 55 | return ""; 56 | } 57 | 58 | public static String resolveCurrentRegionPlaceholders(Player p, String identifier) { 59 | if (p == null) return ""; 60 | PSRegion r = PSRegion.fromLocationGroup(p.getLocation()); 61 | if (r == null) return ""; 62 | 63 | if (identifier.startsWith("currentregion_config_")) { // config options for current region 64 | return ConfigPlaceholders.resolveBlockConfig(r.getTypeOptions(), identifier.substring("currentregion_config_".length())); 65 | } else { // current region placeholders 66 | return resolveRegionPlaceholders(p, r, identifier.substring("currentregion_".length())); // cut out "currentregion_" 67 | } 68 | } 69 | 70 | public static String resolveRegionPlaceholders(Player p, PSRegion r, String identifier) { 71 | if (identifier.equals("owners")) { 72 | return MiscUtil.concatWithoutLast(r.getOwners().stream().map(UUIDCache::getNameFromUUID).collect(Collectors.toList()), ", "); 73 | } else if (identifier.equals("members")) { 74 | return MiscUtil.concatWithoutLast(r.getMembers().stream().map(UUIDCache::getNameFromUUID).collect(Collectors.toList()), ", "); 75 | } else if (identifier.equals("name")) { 76 | return r.getName() == null ? r.getId() : r.getName(); 77 | } else if (identifier.equals("id")) { 78 | return r.getId(); 79 | } else if (identifier.equals("type")) { 80 | return r.getType(); 81 | } else if (identifier.equals("alias")) { 82 | return r.getTypeOptions().alias; 83 | } else if (identifier.equals("is_hidden")) { 84 | return r.isHidden() + ""; 85 | } else if (identifier.equals("home_location")) { 86 | return String.format("%.1f %.1f %.1f", r.getHome().getX(), r.getHome().getY(), r.getHome().getZ()); 87 | } else if (identifier.equals("is_for_sale")) { 88 | return r.forSale() + ""; 89 | } else if (identifier.equals("rent_stage")) { 90 | return r.getRentStage().toString().toLowerCase(); 91 | } else if (identifier.equals("landlord")) { 92 | return r.getLandlord() == null ? "" : UUIDCache.getNameFromUUID(r.getLandlord()); 93 | } else if (identifier.equals("tenant")) { 94 | return r.getTenant() == null ? "" : UUIDCache.getNameFromUUID(r.getTenant()); 95 | } else if (identifier.equals("rent_period")) { 96 | return r.getRentPeriod(); 97 | } else if (identifier.equals("sale_price")) { 98 | return r.getPrice() + ""; 99 | } else if (identifier.equals("rent_amount")) { 100 | return r.getPrice() + ""; 101 | } else if (identifier.equals("tax_owed")) { 102 | return String.format("%.2f", r.getTaxPaymentsDue().stream().mapToDouble(PSRegion.TaxPayment::getAmount).sum()); 103 | } else if (identifier.equals("tax_autopayer")) { 104 | return r.getTaxAutopayer() == null ? "" : UUIDCache.getNameFromUUID(r.getTaxAutopayer()); 105 | } else if (identifier.equals("flags")) { 106 | List flags = new ArrayList<>(); 107 | for (Flag f : r.getWGRegion().getFlags().keySet()) { 108 | if (!r.getTypeOptions().hiddenFlagsFromInfo.contains(f.getName())) { 109 | flags.add(f.getName() + " " + r.getWGRegion().getFlag(f) + "&r"); 110 | } 111 | } 112 | return MiscUtil.concatWithoutLast(flags, ", "); 113 | } else if (identifier.startsWith("flags_")) { 114 | String[] spl = identifier.split("_"); 115 | if (spl.length > 1) { 116 | Flag f = Flags.fuzzyMatchFlag(WGUtils.getFlagRegistry(), spl[1]); 117 | if (r.getWGRegion().getFlag(f) != null) { 118 | return r.getWGRegion().getFlag(f).toString(); 119 | } 120 | } 121 | } 122 | 123 | return ""; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/ChatUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.utils; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import dev.espi.protectionstones.PSRegion; 20 | import org.bukkit.entity.Player; 21 | 22 | import java.util.List; 23 | 24 | public class ChatUtil { 25 | public static void displayDuplicateRegionAliases(Player p, List r) { 26 | StringBuilder rep = new StringBuilder(r.get(0).getId() + " (" + r.get(0).getWorld().getName() + ")"); 27 | 28 | for (int i = 1; i < r.size(); i++) { 29 | rep.append(String.format(", %s (%s)", r.get(i).getId(), r.get(i).getWorld().getName())); 30 | } 31 | 32 | PSL.msg(p, PSL.SPECIFY_ID_INSTEAD_OF_ALIAS.msg().replace("%regions%", rep.toString())); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/MiscUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.utils; 17 | 18 | import dev.espi.protectionstones.ProtectionStones; 19 | import net.luckperms.api.model.user.User; 20 | import net.luckperms.api.model.user.UserManager; 21 | import net.luckperms.api.node.Node; 22 | import org.apache.commons.lang3.StringUtils; 23 | import org.bukkit.Bukkit; 24 | import org.bukkit.entity.Player; 25 | import org.bukkit.permissions.PermissionAttachmentInfo; 26 | 27 | import java.time.Duration; 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | import java.util.UUID; 31 | import java.util.concurrent.ExecutionException; 32 | import java.util.stream.Collectors; 33 | 34 | public class MiscUtil { 35 | 36 | public static String getUniqueIdIntArray(UUID uuid) { 37 | long least = uuid.getMostSignificantBits(); 38 | long most = uuid.getLeastSignificantBits(); 39 | 40 | int[] arr = new int[]{(int) (least >> 32), (int) least, (int) (most >> 32), (int) most}; 41 | return String.format("[I; %d, %d, %d, %d]", arr[0], arr[1], arr[2], arr[3]); 42 | } 43 | 44 | public static String getVersionString() { 45 | return Bukkit.getBukkitVersion().split("-")[0]; 46 | } 47 | 48 | public static Duration parseRentPeriod(String period) throws NumberFormatException { 49 | Duration rentPeriod = Duration.ZERO; 50 | for (String s : period.split(" ")) { 51 | if (s.contains("w")) { 52 | rentPeriod = rentPeriod.plusDays(Long.parseLong(s.replace("w", "")) * 7); 53 | } else if (s.contains("d")) { 54 | rentPeriod = rentPeriod.plusDays(Long.parseLong(s.replace("d", ""))); 55 | } else if (s.contains("h")) { 56 | rentPeriod = rentPeriod.plusHours(Long.parseLong(s.replace("h", ""))); 57 | } else if (s.contains("m")) { 58 | rentPeriod = rentPeriod.plusMinutes(Long.parseLong(s.replace("m", ""))); 59 | } else if (s.contains("s")) { 60 | rentPeriod = rentPeriod.plusSeconds(Long.parseLong(s.replace("s", ""))); 61 | } 62 | } 63 | return rentPeriod; 64 | } 65 | 66 | public static int getPermissionNumber(Player p, String perm, int def) { 67 | return getPermissionNumber(p.getEffectivePermissions().stream().map(PermissionAttachmentInfo::getPermission).collect(Collectors.toList()), perm, def); 68 | } 69 | 70 | public static int getPermissionNumber(List permissions, String perm, int def /* default */) { 71 | int n = -99999; 72 | for (String permission : permissions) { 73 | if (permission.startsWith(perm)) { 74 | String value = permission.substring(perm.length()); 75 | if (MiscUtil.isValidInteger(value)) { 76 | n = Math.max(n, Integer.parseInt(value)); 77 | } 78 | } 79 | } 80 | return n == -99999 ? def : n; 81 | } 82 | 83 | public static String concatWithoutLast(List l, String separator) { 84 | StringBuilder sb = new StringBuilder(); 85 | for (int i = 0; i < l.size(); i++) { 86 | sb.append(l.get(i)).append(i == l.size()-1 ? "" : separator); 87 | } 88 | return sb.toString(); 89 | } 90 | 91 | public static String describeDuration(Duration duration) { 92 | long days = duration.toDays(); 93 | duration = duration.minusDays(days); 94 | long hours = duration.toHours(); 95 | duration = duration.minusHours(hours); 96 | long minutes = duration.toMinutes(); 97 | duration = duration.minusMinutes(minutes); 98 | long seconds = duration.toMillis() / 1000; 99 | 100 | String s = ""; 101 | if (days != 0) s += days + "d"; 102 | if (hours != 0) s += hours + "h"; 103 | if (minutes != 0) s += minutes + "m"; 104 | if (seconds != 0) s += seconds + "s"; 105 | return s; 106 | } 107 | 108 | public static List getLuckPermsUserPermissions(UUID uniqueId) throws ExecutionException, InterruptedException { 109 | UserManager userManager = ProtectionStones.getInstance().getLuckPerms().getUserManager(); 110 | User user = userManager.loadUser(uniqueId).get(); 111 | 112 | List permissions = new ArrayList<>(); 113 | 114 | // add permissions set on the user 115 | permissions.addAll(user.getNodes().stream().filter(Node::getValue).map(Node::getKey).collect(Collectors.toList())); 116 | 117 | // add permissions set on the groups 118 | permissions.addAll(user.getInheritedGroups(user.getQueryOptions()) 119 | .stream() 120 | .flatMap(g -> g.getNodes() 121 | .stream() 122 | .filter(Node::getValue) 123 | .map(Node::getKey)) 124 | .collect(Collectors.toList())); 125 | 126 | return permissions; 127 | } 128 | 129 | public static boolean isValidInteger(String str) { 130 | if (str == null) { 131 | return false; 132 | } 133 | 134 | try { 135 | // this apparently throws NumberFormatException if it is beyond the integer limit, so we catch that 136 | Integer.parseInt(str); 137 | return true; 138 | } catch (NumberFormatException e) { 139 | } catch (NullPointerException e) {} 140 | return false; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/Objs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.utils; 19 | 20 | import java.util.Objects; 21 | 22 | public class Objs { 23 | public static T replaceNull(T obj, T replacementIfNull) { 24 | return obj != null ? obj : replacementIfNull; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/ParticlesUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.utils; 17 | 18 | import dev.espi.protectionstones.ProtectionStones; 19 | import org.bukkit.Bukkit; 20 | import org.bukkit.Location; 21 | import org.bukkit.Particle; 22 | import org.bukkit.entity.Player; 23 | 24 | public class ParticlesUtil { 25 | public static void persistRedstoneParticle(Player p, Location l, Particle.DustOptions d, int occ) { 26 | for (int i = 0; i < occ; i++) { 27 | Bukkit.getScheduler().runTaskLater(ProtectionStones.getInstance(), () -> { 28 | if (p.isOnline()) p.spawnParticle(Particle.DUST, l, 1, d); 29 | }, i*20); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/RecipeUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 ProtectionStones team and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package dev.espi.protectionstones.utils; 19 | 20 | import dev.espi.protectionstones.PSProtectBlock; 21 | import dev.espi.protectionstones.ProtectionStones; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.Material; 24 | import org.bukkit.NamespacedKey; 25 | import org.bukkit.inventory.ItemStack; 26 | import org.bukkit.inventory.Recipe; 27 | import org.bukkit.inventory.RecipeChoice; 28 | import org.bukkit.inventory.ShapedRecipe; 29 | 30 | import java.util.ArrayList; 31 | import java.util.HashMap; 32 | import java.util.Iterator; 33 | import java.util.List; 34 | 35 | public class RecipeUtil { 36 | 37 | private static List recipes = new ArrayList<>(); 38 | public static void setupPSRecipes() { 39 | for (PSProtectBlock b : ProtectionStones.getInstance().getConfiguredBlocks()) { 40 | // add custom recipes to Bukkit 41 | if (b.allowCraftWithCustomRecipe) { 42 | try { 43 | Bukkit.addRecipe(parseRecipe(b)); 44 | recipes.add(getNamespacedKeyForBlock(b)); 45 | } catch (IllegalStateException e) { 46 | ProtectionStones.getPluginLogger().warning("Reloading custom recipes does not work right now, you have to restart the server for updated recipes."); 47 | } 48 | } 49 | } 50 | } 51 | public static void removePSRecipes() { 52 | // remove previous protectionstones recipes (/ps reload) 53 | Iterator iter = Bukkit.getServer().recipeIterator(); 54 | while (iter.hasNext()) { 55 | try { 56 | Recipe r = iter.next(); 57 | if (r instanceof ShapedRecipe && (((ShapedRecipe) r).getKey().getNamespace().equalsIgnoreCase(ProtectionStones.getInstance().getName()))) { 58 | iter.remove(); 59 | } 60 | } catch (Exception ignored) { 61 | } 62 | } 63 | recipes.clear(); 64 | } 65 | 66 | public static List getRecipeKeys() { 67 | return recipes; 68 | } 69 | 70 | public static NamespacedKey getNamespacedKeyForBlock(PSProtectBlock block) { 71 | return new NamespacedKey(ProtectionStones.getInstance(), block.type.replaceAll("[+/=:]", "")); 72 | } 73 | 74 | public static ShapedRecipe parseRecipe(PSProtectBlock block) { 75 | // create item 76 | ItemStack item = block.createItem(); 77 | item.setAmount(block.recipeAmount); 78 | 79 | // create recipe 80 | // key must adhere to [a-z0-9/._-] 81 | ShapedRecipe recipe = new ShapedRecipe(getNamespacedKeyForBlock(block), item); 82 | 83 | // parse config 84 | HashMap items = new HashMap<>(); 85 | List recipeLine = new ArrayList<>(); 86 | char id = 'a'; 87 | for (int i = 0; i < block.customRecipe.size(); i++) { 88 | recipeLine.add(""); 89 | for (String mat : block.customRecipe.get(i)) { 90 | if (mat.equals("")) { 91 | recipeLine.set(i, recipeLine.get(i) + " "); 92 | } else { 93 | if (items.get(mat) == null) { 94 | items.put(mat, id++); 95 | } 96 | recipeLine.set(i, recipeLine.get(i) + items.get(mat)); 97 | } 98 | } 99 | } 100 | 101 | // recipe 102 | recipe.shape(recipeLine.toArray(new String[0])); 103 | for (String mat : items.keySet()) { 104 | if (Material.matchMaterial(mat) != null) { // general material type 105 | 106 | recipe.setIngredient(items.get(mat), Material.matchMaterial(mat)); 107 | 108 | } else if (mat.startsWith("PROTECTION_STONES:")) { // ProtectionStones block 109 | 110 | // format PROTECTION_STONES:alias 111 | String alias = mat.substring(mat.indexOf(":") + 1); 112 | PSProtectBlock use = ProtectionStones.getProtectBlockFromAlias(alias); 113 | if (use != null && use.createItem() != null) { 114 | recipe.setIngredient(items.get(mat), new RecipeChoice.ExactChoice(use.createItem())); 115 | } else { 116 | ProtectionStones.getPluginLogger().warning("Unable to resolve material " + mat + " for the crafting recipe for " + block.alias + "."); 117 | } 118 | 119 | } else { 120 | ProtectionStones.getPluginLogger().warning("Unable to find material " + mat + " for the crafting recipe for " + block.alias + "."); 121 | } 122 | } 123 | 124 | return recipe; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/TextGUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.utils; 17 | 18 | import dev.espi.protectionstones.PSL; 19 | import net.md_5.bungee.api.chat.ClickEvent; 20 | import net.md_5.bungee.api.chat.ComponentBuilder; 21 | import net.md_5.bungee.api.chat.HoverEvent; 22 | import net.md_5.bungee.api.chat.TextComponent; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.command.CommandSender; 25 | 26 | import java.util.List; 27 | 28 | public class TextGUI { 29 | 30 | // page starts at zero, but displays start at one 31 | // pageCommand will be replacing %page% 32 | public static void displayGUI(CommandSender s, String header, String pageCommand, int currentPage, int guiSize, List lines, boolean sendBlankLines) { 33 | int currentLine = currentPage * guiSize; 34 | if (currentPage < 0 || currentLine > lines.size()) { 35 | return; 36 | } 37 | 38 | PSL.msg(s, header); 39 | 40 | for (int i = currentPage*guiSize; i < Math.min((currentPage+1) * guiSize, lines.size()); i++) { 41 | if (sendBlankLines || !lines.get(i).equals(new TextComponent(""))) 42 | s.spigot().sendMessage(lines.get(i)); 43 | } 44 | 45 | // footer page buttons 46 | TextComponent backPage = new TextComponent(ChatColor.AQUA + " <<"), nextPage = new TextComponent(ChatColor.AQUA + ">> "); 47 | backPage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(PSL.GO_BACK_PAGE.msg()).create())); 48 | nextPage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(PSL.GO_NEXT_PAGE.msg()).create())); 49 | backPage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", ""+currentPage))); 50 | nextPage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", currentPage+2+""))); 51 | 52 | TextComponent footer = new TextComponent(ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET); 53 | // add back page button if the page isn't 0 54 | if (currentPage != 0) footer.addExtra(backPage); 55 | // add page number 56 | footer.addExtra(new TextComponent(ChatColor.WHITE + " " + (currentPage + 1) + " ")); 57 | // add forward page button if the page isn't last 58 | if (currentPage * guiSize + guiSize < lines.size()) footer.addExtra(nextPage); 59 | footer.addExtra(ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "====="); 60 | 61 | // display footer only if there are more than one page of entries 62 | if (lines.size() >= guiSize) s.spigot().sendMessage(footer); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/dev/espi/protectionstones/utils/UUIDCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | package dev.espi.protectionstones.utils; 17 | 18 | import com.sk89q.worldguard.WorldGuard; 19 | import com.sk89q.worldguard.util.profile.Profile; 20 | 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | import java.util.UUID; 24 | 25 | public class UUIDCache { 26 | private static Map uuidToName = new HashMap<>(); 27 | private static Map nameToUUID = new HashMap<>(); 28 | 29 | // toLowerCase for case insensitive search 30 | 31 | public static UUID getUUIDFromName(String name) { 32 | if (name == null) return null; 33 | return nameToUUID.get(name.toLowerCase()); 34 | } 35 | 36 | public static String getNameFromUUID(UUID uuid) { 37 | if (uuid == null) return null; 38 | return uuidToName.get(uuid); 39 | } 40 | 41 | public static boolean containsName(String name) { 42 | if (name == null) return false; 43 | return nameToUUID.containsKey(name.toLowerCase()); 44 | } 45 | 46 | public static boolean containsUUID(UUID uuid) { 47 | if (uuid == null) return false; 48 | return uuidToName.containsKey(uuid); 49 | } 50 | 51 | public static void storeUUIDNamePair(UUID uuid, String name) { 52 | if (uuid == null || name == null) return; 53 | uuidToName.put(uuid, name); 54 | nameToUUID.put(name.toLowerCase(), uuid); 55 | } 56 | 57 | public static void removeUUID(UUID uuid) { 58 | if (uuid == null) return; 59 | uuidToName.remove(uuid); 60 | } 61 | 62 | public static void removeName(String name) { 63 | if (name == null) return; 64 | nameToUUID.remove(name.toLowerCase()); 65 | } 66 | 67 | public static void storeWGProfile(UUID uuid, String name) { 68 | WorldGuard.getInstance().getProfileCache().put(new Profile(uuid, name)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/resources/config.toml: -------------------------------------------------------------------------------- 1 | # Please do not change the config version unless you know what you are doing! 2 | config_version = 16 3 | uuidupdated = true 4 | region_negative_min_max_updated = true 5 | 6 | # --------------------------------------------------------------------------------------- 7 | # Protection Stones Config 8 | # Block configs have been moved to the blocks folder. 9 | # To make new blocks, copy the default "block1.toml" and make another file (ex. "block2.toml") 10 | # Does your config look messy? It's probably because of gradual config updates. Consider using the default configs. 11 | # If you need the default configs again, you can get it from here: https://github.com/espidev/ProtectionStones/tree/master/src/main/resources 12 | # --------------------------------------------------------------------------------------- 13 | 14 | # Cooldown between placing protection blocks (in seconds). -1 to disable. 15 | placing_cooldown = -1 16 | 17 | # Set to true to not block server startup for loading the UUID cache. 18 | # /ps add and /ps remove will not work for offline players until the cache is finished loading. 19 | async_load_uuid_cache = false 20 | 21 | # Whether or not to allow regions to have identical names (from /ps name). 22 | # If this is set to true, players will have to use numbers after the name if they encounter duplicates. 23 | allow_duplicate_region_names = false 24 | 25 | # Time in seconds between /ps view attempts. 26 | # Can prevent lag from spamming the command. 27 | ps_view_cooldown = 3 28 | 29 | # Base command for protection stones (change if conflicting with other commands) 30 | base_command = "ps" 31 | 32 | # Aliases for the command 33 | aliases = [ 34 | "pstone", 35 | "protectionstone", 36 | "protectionstones" 37 | ] 38 | 39 | # Whether or not to drop items on the ground if the inventory is full (ex. during /ps unclaim) 40 | # If set to false, the event will be prevented from happening, and say that inventory is full 41 | drop_item_when_inventory_full = true 42 | 43 | # Whether or not regions placed have to be either next to or overlapping existing regions the player already owns. 44 | # This can make the world cleaner and have less scattered regions. 45 | # Set the number of regions of non-adjacent regions with the permission protectionstones.adjacent.x (default is 1, -1 to bypass) 46 | # Also can bypass with protectionstones.admin 47 | regions_must_be_adjacent = false 48 | 49 | # Whether or not to give players the option to merge new regions with ones they already own (overlapping) 50 | # to create a new large region. Can merge any regions with protectionstones.admin 51 | # Requires the permission protectionstones.merge to use (with /ps merge) 52 | # NOTE: Due to the limitations of WorldGuard, merged regions will ignore y_radius and go from bedrock to sky 53 | # since polygon regions can only be 2D, not 3D 54 | allow_merging_regions = true 55 | 56 | # Whether or not to allow merged regions to have holes in them (merging a bunch of regions in a circle with the inside not protected). 57 | # This is only checked during the merge process, it will not unmerge regions with holes already. 58 | allow_merging_holes = true 59 | 60 | # Whether when players join, by default they have protection block placement toggled off (equivalent to running /ps toggle) 61 | default_protection_block_placement_off = false 62 | 63 | # If you do not have LuckPerms, ProtectionStones is unable to determine the limits of offline players (since it depends 64 | # on permissions), and so it requires players to be online. Set this to true if your server does not need limits (and so 65 | # the check is unnecessary). 66 | allow_addowner_for_offline_players_without_lp = false 67 | 68 | # Whether or not members of a region can /ps home to the region. 69 | allow_home_teleport_for_members = true 70 | 71 | [admin] 72 | # Whether /ps admin cleanup remove should delete regions that have members, but don't have owners (after inactive 73 | # owners are removed). 74 | # Regions that have no owners or members will be deleted regardless. 75 | cleanup_delete_regions_with_members_but_no_owners = true 76 | 77 | [economy] 78 | # Set limits on the price for renting. Set to -1.0 to disable. 79 | max_rent_price = -1.0 80 | min_rent_price = 1.0 81 | 82 | # Set limits on the period between rent payments, in seconds (86400 seconds = 1 day). Set to -1 to disable. 83 | max_rent_period = -1 84 | min_rent_period = 1 85 | 86 | # Set taxes on regions. 87 | # Taxes are configured in each individual block config. 88 | # Whether or not to enable the tax command. 89 | # If you already have regions, you may want to set each one to have an autopayer (player that automatically pays taxes). 90 | # This can be done with /ps admin settaxautopayers, which updates every region on the server with an autopayer from their owners list. 91 | tax_enabled = false 92 | 93 | # Notify players of outstanding tax payments for the regions they own. 94 | tax_message_on_join = true 95 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: ProtectionStones 2 | version: ${version} 3 | description: ${description} 4 | authors: [EspiDev] 5 | 6 | depend: [WorldGuard, WorldEdit] 7 | softdepend: [Vault, PlaceholderAPI, LuckPerms] 8 | main: dev.espi.protectionstones.ProtectionStones 9 | api-version: 1.17 10 | 11 | permissions: 12 | protectionstones.create: 13 | description: Protect a region by placing a ProtectionStones block. 14 | default: op 15 | protectionstones.destroy: 16 | description: Allow players to remove their own protected regions (block break). 17 | default: op 18 | protectionstones.unclaim: 19 | description: Allow players to unclaim their region using /ps unclaim. 20 | default: op 21 | protectionstones.unclaim.remote: 22 | description: Allow players to unclaim their region remotely using /ps unclaim [list|region-id]. 23 | default: op 24 | protectionstones.view: 25 | description: Allows players the use of /ps view in their own regions. 26 | default: op 27 | protectionstones.view.others: 28 | description: Allows players the use of /ps view in regions they are not a part of. 29 | default: op 30 | protectionstones.info: 31 | description: Allows players the use of /ps info. 32 | default: op 33 | protectionstones.info.others: 34 | description: Allows players to use /ps info in unowned regions. 35 | default: op 36 | protectionstones.get: 37 | description: Allows players the use of /ps get. 38 | default: op 39 | protectionstones.give: 40 | description: Allows players the use of /ps give (give protectionstones to others as admin). 41 | default: op 42 | protectionstones.count: 43 | description: Allows players the use of /ps count. 44 | default: op 45 | protectionstones.count.others: 46 | description: Allows players the use of /ps count [player]. 47 | default: op 48 | protectionstones.list: 49 | description: Allows players the use of /ps list. 50 | default: op 51 | protectionstones.list.others: 52 | description: Allows players to do /ps list [player]. 53 | default: op 54 | protectionstones.hide: 55 | description: Allow players to hide their ProtectionStones block. 56 | default: op 57 | protectionstones.unhide: 58 | description: Allow players to unhide their ProtectionStones block. 59 | default: op 60 | protectionstones.setparent: 61 | description: Allow access to /ps setparent. 62 | default: op 63 | protectionstones.setparent.others: 64 | description: Allow players to set their region to inherit properties from other regions they don't own. 65 | default: op 66 | protectionstones.name: 67 | description: Access to the /ps name command. 68 | default: op 69 | protectionstones.home: 70 | description: Access to the /ps home command. 71 | default: op 72 | protectionstones.sethome: 73 | description: Access to /ps sethome. 74 | default: op 75 | protectionstones.tp: 76 | description: Access to /ps tp command. 77 | default: op 78 | protectionstones.tp.bypasswait: 79 | description: Bypass the wait time set in the config for /ps home and /ps tp 80 | default: op 81 | protectionstones.tp.bypassprevent: 82 | description: Bypass prevent_teleport_in option in config 83 | default: op 84 | protectionstones.priority: 85 | description: Allows players to set their region's priority. 86 | default: op 87 | protectionstones.owners: 88 | description: Allows players to add or remove region owners. Allows players to use /ps info owners command. 89 | default: op 90 | protectionstones.members: 91 | description: Allows players to add or remove region members. Allows players to use /ps info members command. 92 | default: op 93 | protectionstones.flags: 94 | description: Allows players to set their region flags. 95 | default: op 96 | protectionstones.rent: 97 | description: Allows players to use the /ps rent command. 98 | default: op 99 | protectionstones.buysell: 100 | description: Allows players access to /ps buy and /ps sell. 101 | default: op 102 | protectionstones.tax: 103 | description: Allows players to access /ps tax commands. 104 | default: op 105 | protectionstones.toggle: 106 | description: Allows players to toggle ProtectionStones placement. 107 | default: op 108 | protectionstones.region: 109 | description: Allows players to use the /ps region commands. 110 | default: op 111 | protectionstones.merge: 112 | description: Allows players to merge their regions with other regions they own. 113 | default: op 114 | protectionstones.admin: 115 | description: This permission allows users to override all ProtectionStones regions and use /ps admin and /ps reload. 116 | default: op 117 | protectionstones.superowner: 118 | description: Allows players to override region permissions. 119 | default: op --------------------------------------------------------------------------------