diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 000000000..0d709ba12 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,25 @@ +name: Prison Build + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Gradlew permission + run: chmod +x gradlew + - name: Build + run: ./gradlew build + + - name: Upload Jar + uses: actions/upload-artifact@v2 + with: + name: Prison + path: prison-spigot/build/libs/Prison.jar diff --git a/PrisonSpigotMC.bbcode.txt b/PrisonSpigotMC.bbcode.txt new file mode 100644 index 000000000..d2873c960 --- /dev/null +++ b/PrisonSpigotMC.bbcode.txt @@ -0,0 +1 @@ +[size=200][center][font=Verdana][color=#e69138][b]Prison [/b][/color][/font][/center][/size] \ No newline at end of file diff --git a/README.md b/README.md index bba1119d7..d6c2f0298 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![License](https://img.shields.io/badge/license-GPL%20License%20v3-blue.svg)](LICENSE.md) [![Build Status](https://travis-ci.org/MC-Prison/Prison.svg?branch=master)](https://travis-ci.org/MC-Prison/Prison) -[![Discord](https://discordapp.com/api/guilds/332602419483770890/widget.png)](https://discord.gg/396ed5F) +[![Discord](https://discordapp.com/api/guilds/332602419483770890/widget.png)](https://discord.gg/DCJ3j6r) 1. [What is Prison?](#what-is-prison) 2. [Why should I use Prison?](#why-should-i-use-prison) diff --git a/changelog_v3.2.x.md b/changelog_v3.2.x.md index b72a3c3e1..9d0f0b811 100644 --- a/changelog_v3.2.x.md +++ b/changelog_v3.2.x.md @@ -2,2021 +2,435 @@ ## Prison Build Logs for v3.2.x +## Build logs + - **[v3.2.3-alpha - Current](changelog_v3.2.x.md)** + - **[v3.2.0 - 2019-12-03](docs/prison_changelog_v3.2.0.md)** + - **[v3.2.1 - 2020-09-27](docs/prison_changelog_v3.2.1.md)** + - **[v3.2.2 - 2020-11-21](docs/prison_changelog_v3.2.2.md)** + + Greetings! I'm delighted that you are interested in the build logs for the Prison plugin. I'm wanting to provide a more formal documentation as to what is going on in each build so you have a better idea if it may be something that you need. -## tag v3.2.2-alpha.14 - 2020-11-21 - - -* **v3.2.2-alpha.14 - 2020-11-21** -Bump version... preparing for v3.2.2 bug fix. - - -* **Refactored where the commands that are outside of the modules are registered.** -They are now registered within the function where the modules are registered to allow the related commands to either be registered or not, based upon the modules. -Refactored how some of the commands/configs are setup to be more flexible, or to better follow the standards of how prison has been instantiating them (ListenersPrisonManager). - - -* **Split out the gui ranks and gui mines commands** from the main spigot gui commands. This allows them to be enabled on their own, or more importantly, prevent them from being registered if the modules are not loaded. - - - -* **Changes to the gui commands to prevent console from running a few gui commands.** -Also remove the alias of "prisonmanager" for "gui". -It was reported that when a non-admin tried to use /mines that it was giving the error message associated with /gui. Cannot see a direct relationship there, but hard linked /mines to /gui mines by calling the function directly instead of resubmitting the command. Not sure if this fixes the issue, but I was unable to reproduce it. - - -* **Minor changes** -Add more to the BaseCommands and start to hook them up. Fix usage of getting the current economy. - - -* **To prevent prestige related commands from being registered with bukkit**, -pulled prestige related commands in to their own command class and then conditionally register them if prestiges are enabled. Cleaned up a few other things such as remove use of deprecated functions and -moving the implementation of isPrisonConfig to SpigotPrison to simplify a few things and eliminate duplication. - - -* **Fixed a problem with bukkit on a paper v1.16.4 server where the Bukkit.getOfflinePlayers() was returning either a null player, or a player had a name that was null.** - - -* **v3.2.2-alpha.13 - 2020-11-15** - - -* **Updates to the GUI: many.** -Moving configs to a common package to better manage them, or to prepare to merge them in the future. Many other fixes and enhancements. - - -* **Updated the SpigotMineBlockPercentageGUI to include a Close button and to show the selected block top and center.** -Also provided links back to the block list gui. Setup the parameters to return back by setting the font color to black so it is visible that they exist as the players hover. - - -* **Fixed issue with GUI block list.** -Using a combination of XMaterial and ItemStacks, its able to display the viewable blocks. Added Prior button to go back to prior page. Got the Next page button working (it was incorrectly just blindly deleting the first two characters of the button name; changed it to strip color so it is not destructive. Setup this page to be able to return to it from other pages. Confirmed that this works with spigot v1.8.8 and spigot v1.16.3. - - -* **Fix issue with GUI not being able to display red or lime stained glass panes** -due to use of material instead of ItemStacks. This applies to mc v1.8 through mc v1.12 and they display as plain glass panes (no colors). - - -* **Added a SpigotPrison function to strip all colors from text.** -Needed in the GUI to hide extra parameters. - - -* **GUI direct support for ItemStacks when creating buttons for mc v1.8 through mc v1.12. ** -With the use of magic numbers with Minecraft versions less than 1.13 the use of Materail to create ItemStacks fails to get the correct type if magic numbers are involved. Created a new createButton function to work directly with item stacks so the proper blocks can be used with mc v1.8 through v1.12. - - -* **Additions to PrisonBlock handlers to provide more utility functions** -and to solve a few complex challenges. Removed NULL_BLOCK from the valid block lists. - - -* **Found function names that started with capital letters and changed them to lower case.** -Function names should never be capitalized since that would imply they are classes, or similar objects, and not functions. - - -* **Compile error with the removal of the prison core gui...** -Removal of this code was forgotten when removing the prison core gui code. Not sure how that passed the compiler before committing to git? - - -* **cleaned up unused imports in the gui code; were causing compile warnings.** - - -* **New feature! Hooked the prison GUI up to the new prison command manager.** -Assigned aliases so as to preserve backwards compatibility with admins who are used to the prisonmanager command. -The /prisonmanager command has been replaced with just /gui. Tested and appears to be working well. Can do /gui mines, /gui ranks, /gui prestige, /gui prestiges. - - -* **Added /mtp as an alias to /mines tp.** - - -* **New GUI config system** -- It's an improvement. Has many code changes -- Deleted the GuiListener.java class, only SpigotPlatform was using it so nothing should break. - - -* **New Feature! Tab complete is now functional with prison's command handler.** -When typing in prison related commands, you can now press tab to complete the typing for you if there was only one option available, or it will fill in common letters until you need to make a choice. Also typing in a command pressing space then tab shows all available options. In game is slightly different that in console, where in game show a ghosting of the command where you are typing so tabbing will select that option. -Works on spigot 1.8 through 1.16.x. Also works in console. Functional with aliases too. - - -* **New Feature! Command Aliases!** -Add the complexities of supporting aliases in the prison command handler. Each command can have one or more aliases mapped to almost any level of paths. -This also includes a rich support of the sub-command and help listings to better identify which commands are aliases and also what aliases are available. There is room for enhancements that will be added soon. - - -* **v3.2.2-alpha.12 - 2020-11-10** - - -* **removed the trailing &f from the rank tag** -This was within the new feature /ranks autoConfigure. It was reported that there were issues within the plugin Scoreboard-r by RienBijl that data was being truncated and lost. Looking in to the issue it was found that there was a stray &f at the end of a tag. It had no impact, but it was removed anyway since it does nothing. It was determined that the scoreboard-r plugin is buggy and was causing errors. - - -* **New Feature: Now provides the capture of the actual label that a command is registered with Bukkit when there is a conflict.** The prison Command Handler now uses the registered label when displaying any of the sub commands or list of all registered root commands. This will allow the users to know what commands they actually have to enter to get them to work, instead of guessing when there is a conflict. - - -* **Improve block matching for pre mc v1.13.0** -For the 1.8.x material types in prison, there exists different states with the data value that could result in block types that are unknown. Some of it may be orientation or degree of flowing water, or even wetness of soil. I've seen it with leaves of different shades, or even with logs. -The idea here to fix this issue is not so much that we don't know the block type as much as it shouldn't matter the slight variations in the data field. Therefore if we fail to match on the id and data, then go off of the material name. That's a good fallback. - - -* **Bug fix: Fix incorrect display of no other mines near for /mines whereami** -If the player was standing in a mine and there are no other mines around, it used to show the mine they are in, plus say there are no other mines within 150 blocks. -Now it will not show the "no other mines in 150 blocks" message. - - -* **Mines Blocks GUI Fix** - - -* **Bug Fix: Found a bug in the command registration code** that could result in failing to properly register commands. This would have been an issue if there were upper case letters in a command, since all commands are converted to lowercase when added, but when checking to see if a subcommand was already processed (ie... the "set" in the following two commands: /mines set tag, /mines set resetTime). The symptoms would be missing commands at runtime. I actually have seen this failure in the past, and realized that all commands should be entered as lowercase due to this error. Now it should work correctly. - - -* **Clarify the role of a CommandHandler field that is used in a situation of when there is a command collision.** - - -* **Fix typo: In the /mines command add function, a & was placed one character to the right of where it should have been.** - - -* **Added an unregister all for the commands and hooked it up on the plugin's onDisable.** - - -* **Fixed issue with dropping of inventory.** -Had a ! where it shouldn't have been and forgot to hook up the new messageId variable so the warning can change. -I'm not so sure about messaging this way, using the action bar, but don't want to flood chat with a ton of messages either. Would have to put a limiter on the chat messages? - - -* **Fixed an index out of range issue in the gui.** -Was 45 when should have been 44. - - -* **New Feature: Added XP calculations to the block break (auto pickup) function** -which can be disabled. Give the option to drop the xp as orbs (default) or give it directly to the player with no orbs. - - -* **It was realized that dropItemsIfInventoryIsFull was not hooked up.** -Hooked it up. - - -* **Update some docs and added a few screen prints.** -Updates to a few documents to reflect some of the more recent updates to prison. - - -* **Updates to the IntegrationManager** so the variable is more consistent and especially the message for WorldGuard integration is clear that it is not an error that it is not yet active. - - -* **Change the command /prison alerts so they can be ran from the console** since it made no sense why the console was locked out from using them. -Slight changed the information for /prison gui that shows that it could be preferred to configure the autofeatures. - - -* **Changed the perms to lower case, specifically the mine/rank name. Should have been lower case.** - - -* **Had the wrong block name for dark_oak_planks (thought I fixed that already).** - - -* **v3.2.2-alpha.11 - 2020-10-29** - - -* **For /ranks autoConfigure: Almost forgot to add the removal of the mines.tp. when demoting a player.** - - -* **Added a new feature: can now set the area of a mine based upon location of your feet.** -This allows you to create a virtual mine, then set its location where you're standing or flying, then you can resize it. This bypasses the need of having to use a wand to create a mine or define it's size and location and allows it to be defined in mid air or in a void world where you cannot click on any blocks. - - -* **Fix the report on how many blocks are in a new mine.** It was reporting on surface area and not block count. -Fixed an issue with world being saved correctly. When a virtual mine was converted to a real mine, the world and world name were not always being updated. Fixed it by not only being more aggressive when setting the Bounds, but also when saving the mine. - - -* **Reenable the compatibility cache on block mapping.** -This eliminates related failures to map blocks, which will prevent wasted time continuously looking them up. - - -* **A few more tweaks to the block types to fix missing block from a pattern.** - - -* **Added the ability to add the "force" option to the /mines set liner command.** -Normally the command only adds the liner if there is not air so that the mine's liner does not extend above the ground level, and it ends at ground level. -Force is intended to cause the liner to work in a void area where all there is only air. Otherwise you would have to place blocks on the outside to "trick" the liner to work. - - -* **Fixed the block names for the new liner patterns.** -I accidentally added them based upon actual block names and not what is mapped to the prison block names or the new block types which are keyed to XMaterials. This fixed them. - - -* **Added a compatibility reference to help map it to XMaterials.** -Jungle_planks - - -* **Enhance the ranks auto configure by adding support for GroupManager permission plugin.** -Also added the remove permission of the next higher rank so as to support demotions. - - -* **Added three new patterns to the MineLinerBuilder.** - - -* **Minor code improvements for the player GUI and this should also fix the null value.** - - -* **The gui was trying to pass null strings to this format function.** -If the parameter value is null, then just return an empty String, otherwise try to format it. - - -* **Simplify the error message if a player does not have access to tp to a mine** -they should not be seeing anything pertaining to perms. - - -* **Hooking up more of the prison's mines commands to properly, and fully, use the new prison block model.** -The new PrisonBlocks are now being validated against the dynamic list of valid blocks that are available on the server that is running prison. So within the block search, as one example, it will only show valid blocks that can be used; the old block model would show all possible blocks within prison, some of which may not have been blocks. - - -* **Enhancements for Prison's new block model** -Enhance the PrisonBlock to use block instead of mineable for better consistency with bukkit and spigot use of blocks. Also set block name to be always lower case for easier searches. -PrisonBlockTypes has been enhanced to be able to search for blocks by name. This is using a b-tree for quicker retrieval instead of loop though all available blocks. -When valid blocks are added to PrisonBlockTypes (the valid blocks that exist on that server) they are have their isValid and isBlock values set to true. Also now using XMaterial names for better long term consistency that will not change if the admins upgrade or down grade their servers. - - -* **Hook PrisonBlockTypes up to the Prison object.** -This will load a list of new block types at server startup that have been validated against the version of minecraft that is running. This will ensure that the only blocks that the player will see listed in block searches, as one example, will be blocks they can actually use. This is highly dynamic based upon the server and not the complier. -This is preparing for the use of the new block model by giving access to valid blocks within many of the /mine related commands. - - -* **Remove more of the Items related code** which has not been used for awhile. ItemManager and troubleshooters related to that. - - -* **Reenabled the caching of null values when translating from one material type to another.** -This prevents looking up a failed code many times and only allows one error message to be logged to the console. - - -* **v3.2.2-alpha.10 - 2020-10-26** -Version bump due to the significance of the last bug fix. - +# V3.2.3 2020-12-25 -* **Major bug fix: Eliminated the in prison caching of players.** -This collection was not able to deal with players reconnecting to the server, which would give them new player objects. The issue was that prison would have an obsolete (zombie) copy of the player and their inventory. So if any operations would be performed on the inventory, such as giving a selection wand, it would be placed in the orphaned object and the player would never get it. The only way to "fix" this issue would be to restart the server and then it would fail once they would log out and reconnect. -This was confirmed a problem with 1.9.2, 1.13.4, 1.15.2, and 1.16.3. It was not an issue with spigot v1.8.8. This did not impact players retrieved from events. -This fixes the issue by removing prison caching of the players. Now all instances of the players being used within prison are now live bukkit objects. -I suspect this issue has been within prison for a long time. Not sure why no one reported it before, or if they did, it was not clear how to reproduce this issue and the ones reporting it may not have been able to provide enough information to reproduce it. The way it is reproducable is to login, get a /mines wand or have prison interact with the player's inventory, then log out and then back in. Then /mines wand will fail to place it in the real player's inventory. It will only go in to the prison cache. -* **v3.2.2-alpha.9e - 2020-10-26** -* **Bug fix: When a world is not available upon startup** it will try to set the boundaries for the mine. In doing so, it will try to extract the correct world to enable it and to remove the virtual status if it was set. If the world has not yet been loaded (ie... if you're using multiverse) then this was causing an error for that mine. This now will only mark the mine as disabled and allow the multiverse plugin to trigger the completion of the mine loading event for that mine (as it has been doing before virtual mines were added). -If a mine has the boundaries set and if it was disabled or virtual, then make it a real mine. Have checks to ensure the world is available, if not, then disable the mine. +# V3.2.3 2020-12-25 +**Merry Christmas!!** +Release of next bug update. -* **v3.2.2-alpha.9d - 2020-10-26** +* **fix for placeholdermanager's setup** -* **New feature: Dump player's inventory to console** -This is useful to check status of various prison related functions. -One area that this maybe useful with some players reporting that they are getting a Prison Selection Wand, but it's not showing up in their inventory, although inspection of their inventory is showing they are getting it. +* **Placeholder refactoring to prepare for the use of dynamic customization by the users**, such as customizing each and every bar graph, or number formatting, where each use of the same placeholder could have different settings. -* **v3.2.2-alpha.9c - 2020-10-26** +* **Added 4 new placeholders for rank number** +The new placeholders identifies the ladder position of a rank on their ladder. The lowest rank has a value of 1. These prison_rn, prison_rank_name, prison_rn_laddername, and prison_rank_number_laddername. -* **Fix to GUIs and Close button conflict** -Fix to Mines GUI lore issues for Virtual Mines +* **Setup editing options for BlockEvents** +so there are now an add, eventType, list, mode, percent, permission, and remove options to work with the BlockEvents so once created they can be better maintained without having to delete them and readd them. -* **v3.2.2-alpha.9b - 2020-10-26** +* **V3.2.3-alpha.13 2020-12-24** -* **Fixes issue with not enabling a virtual mines** -when the area is set with the command: /mines set area help +* **Added the ability to tie a BlockEvent to either a normal block break event, or a TE Explosion event, or both.** +This allows a more focused approach and flexibility. +Hooked this up to a few more things and finalized more of it. -* **Fixes to some blocks and use of XMaterial for STAINED_GLASS** -This allows for multi-version support since material names have changed at 1.13. This supports 1.8 through 1.16 now. This fixes an exception for versions less than 1.13. +* **Found some obscure bugs with the command handler and fixed it. Was generating a NPE.** -* **Fixes to config, now you'll not see any "§" but only "&"** -There might be some strings that won't translate that, If you spot them (like lores with an & instead of color), please report it. This fixes an issue for some user's environment not being able to properly translate the `§` when generating the GUI config files and language files. Basically the file's UTF-8 encoding was being treated as ASCII and that character was being converted to a hex value that could not be translated back to something usable. +* **Changes to ranks autoConfigure to force a generation if ranks and mines already exist.** +If there is a conflict with a preexisting rank, it iwill be skipped and so will the generation of the mine by the same name. -* **v3.2.2-alpha.9a - 2020-10-26** +* **Hook up the auto assignment of mine liners to the mines when running the ranks autoConfigure command.** +The selection of the liners is random and are applied to the walls and bottom using the force setting to ensure they generate in a void world. -* **Enable OPs to tp players even from console.** -Also if the player who is running the command is the same as the name being passed as a parameter, then allow it. +* **Add support for assigning random liners to the auto generated mines.** +Does not include the last LinerPattern since it is for repair. -* **v3.2.2-alpha.9 - 2020-10-26** +* **More work on the mine liner. Pretty much working well with /mines set size.** +Still need to hook up to a few other areas. -* **Added the ability to move a mine but am not enabling it.** -It is not behaving as well as it should. The tracer is being left behind when it shouldn't. -Other adjustments to the sizing and liner functions have been made too. +* **Hooking up the saving of mine liners so they can eventually be used to regenerate themselves when resizing or moving the mine.** +Still needs more work, but getting closer. -* **Adjustments to getting the MineLinerBuilder working.** -These here are minor changes that makes a few aspects work slightly better. +* **Update some of the changelog docs.** +It was getting very long, so broke them out in by release version for easier tracking of changes. -* **Change the way the caching is working on block mappings.** -Removed the caching of no-hits on block conversions. Normally recording the no-hit conditions will result in significant performance improvements, but removed them for now to make sure they are not causing issues. Will have to reenable them (rewrite the code) in the future. -* **Provided more detailed reports on missing block types** -from spigot mapping to prison's old block types. Some of these will be needed until we can get the new block model fully functional. +* **Refactored some of the Mine related classes** to better organize them since they will be undergoing some changes soon. -* **Added a few new block types for v1.13.** -The major one that fixed some significant issues was GRASS_BLOCK since it used to be named GRASS in older versions of minecraft, but now GRASS is just the plant. -Also added 18 new log types for v1.13 and newer. -* **Removed traces of the enableMineTracer within the Platform object.** +* **Initial support for hex colors.** +Works, but its a pain until I can auto parse the hex automatically. But for now it can be entered and will work well with v1.16.x and will degrade to something reasonable for even v1.8.8. +So instead of using &#abcdef for right now, you need to enter it as &x&a&b&c&d&e&f. I'll hook up the proper translator later, but the expanded format should always work. -* **More improvements to the /mines set size and the /mines set liner commands.** -Added ladders to the liner, and also added repair to undo the liner based upon the surrounding blocks. Appears to be working well for spigot 1.8.8. +* **3.2.3-alpha.12 2020-12-21** +* **Fixes a potential issue where players are attempted to be added in an async thread which will end with a failure since the commands on rankup cannot be ran in an async thread.** +This now detects if the thread is async (not the primary bukkit thread) and then submits a future sync task to run in zero ticks that will add the new player to Prison, which will result in a rankup. -* **Rank Tags modified to accept spaces** -To match the capabilities of the Mine Tag, the rank tag was adjusted to allow spaces. The command /ranks set tag was also changed to remove the tag if desired. Also changed the /ranks create command to accept spaces in the tag name too. +* **Move the PrisonRunnable out of the Mines module and placed it in core since it needs to be used elsewhere.** -* **v3.2.2-alpha.8 - 2020-10-22** +* **RankUpEvent now contains more information and can now cancel a rankup.** +As a result to allow the canceling of a rankup, the rankup code had to be modified to fire the event before anything is applied to the rankup. -* **New Feature: Now able to line a mine based upon the selection of edges and patterns.** -This feature helps players to get up and running their prison a lot faster. -Many additional patterns can be added in the future. Supports 2d patterns that are from 1x1 to any larger size. +* **3.2.3-alpha.11 2020-12-19** -* **Bug fix? Needed to add TokenEnchant to the softdepend** -to prevent a java.lang.NoClassDefFoundError with the class com/vk2gpz/vklib/logging/ColorConsoleLogger. -Not really sure if I can call this a Prison bug since it appears to originate from within the TE API code base. But this works around their potential short comings. +* **Reenabled the global broadcast of rankups**, which this time it's hooked p to the config setting broadcast-rankups in the config.yml file. -* **Bug fix! Trying to format an already formatted item... oof!!** -This had everything to do with formatted currency amounts in placeholders. +* **Enabled new feature prestige.resetMoney** +that will control if the player's money is reset upon presetiging. The new permission is `presetige.resetMoney`. If the permission is not set, then it will default to true. This also changes the configs in config.yml with prestiges being deprecated but will remain for a while. -* **Disabled the loading of the /items.csv file** -since that is obsolete and not working anymore. The items.csv file has been removed from the project since people were thinking they can just modify that file to add custom blocks. Nope... - -* **Add logging to count how many blaze rods the player has before and after issuing the /mines wand command.** -there have been a few reports that it does not work, but I cannot reproduce the error. So this is step one in confirming if they actually get the blaze rod or not. -One possibility could be that another plugin is canceling the event so the player never gets the blaze rod. - - -* **v3.2.2-alpha.7b - 2020-10-21** - - -* **Temp pulled alpha.7** Someone said the were getting a lot of errors with this release. Hence the past two fixes. - - -* **Fix potential issue where the user tries to use a % % as escape characters when they should be using { } instead.** -It was causing a failure when trying to redisplay the text as for the % was trying to be used as a placeholder when fed through the String.format command. - - -* **New feature: /mines set size** -Can now adjust the mine size by specifying the edge and adjustment amount. Edges are top, bottom, north, south, east, west, and walls. -When adjusting the size, it automatically goes in to tracer mode so the mine's dimensions are easily seen. - - -* **v3.2.2-alpha.7 - 2020-10-21** - - -* **Created the code to add blocks to virtual mines when they are being generated with the /ranks autoConfigure command.** -Blocks are setup in a List with the least valuable to the most valuable. Then it's a sliding window of selecting blocks from the lowest mine to the highest ranked mine. The percentage per blocks are 5, 10, 20, 20, 20, 25 where the most valuable are least represented. - - -* **Added a few new blocks to prison's old block model.** -These are actually duplicates of what already exists, but these are instead named to mirror XMaterial names. The reason for this is to ensure consistency between the two block models used for testing. -Removed the items.csv document since it is not being used anymore and will only cause confusion if admins think they can add new blocks through that file. - - - -* **Added some internal reporting of the data contents.** -Most of this will be used with logging in the /ranks autoConfigure and also jUnit testing. - - -* **Error logging needs to throw these stack traces** since thats really the only way to get the details we need to fix the problem. -A throw was eliminated, but needs to be added back. - - -* **New Feature: Added 12 new placeholders including aliases.** -Added formatted placeholders for player's costs. Added a new placeholder for player balance. -Created a PlaceholdersUtil class to perform some common functions, such as formatting an amount to include a metric prefix. - - -* **tag v3.2.2-alpha.6a - 2020-10-19** - -* **Fix issue with mine name** -that is related to virtual mines if not creating a virtual mine. An extra space was added to the end of the mine name which was triggering an error message about spaces in mine names. - - -* **Add a second perm to allow mines.tp.** -to be added to each rank that is auto generated. -will provide support soon for EssentialsX warp... - - -* **New Feature: Allow the user to specify the material name in the GUI config files to use for a mine's block type.** -The material names are based upon XMaterial for consistancy throughout all versions of spigot/minecraft. -The format is: Options.Mines.MaterialType. - - - -* **New feature: produce a warning when the first parameter of any prison command is not a CommandSender.** -Parameters using Player has been causing stack traces under different circumstances because the prison command handler ALWAYS passes a CommandSender object as the first parameter, therefore that is the type it needs to be to prevent a method type mismatch exception. The new changes will provide a warning when starting prison; it should ideally be caught at compile time but it can't. - - - -* **tag v3.2.2-alpha.6 - 2020-10-19** Bump the version due to significant changes. -It needs more testing prior to being released to the alpha channel. - - -* **Bug fix: prevent the config files for gui and it's messages from loading from the file every single time it is accessed.** -And they were accessed everywhere, and for one message, even three to four times just to generate one message. -This should improve performance significantly for the gui overall. - - -* **Provide a way to get the counts of a given ModuleElementType.** -Allows for access in modules that don't have direct access to other modules. - - -* **Wrapping up changes on virtual mines** -Fixes issues with virtual mines. Allows full configurations of virtual mines except for setting the area and spawn point. - - -* **Bug Fix: Found the wrong parameter was being used on a few commands** -Fixes some hard to find problems where the wrong parameter was being supplied to the commands. It would work most of the time, but under some conditions it would fail. Was using a parameter of Player instead of CommandSender. - - -* **Added a logCore feature that does not try to translate colors...** -this helps to bypass exceptions if an exception is trapped. -Added a dump when parameters on messages are not properly paired. This will be critical when all messages will be externalized and subject to users messing up the formatting placeholders. - - -* **New feature! Auto generate Ranks and Mines!!** -This is based upon the work of Gabryaca, but I reproduced it to be a part of the RanksCommand and gave it the capability of generating virtual mines too! -This is actually a starting point of what it can become. I not only added the creation of mines, but I also hooked it up to link the mines and ranks together as it generates them. - - -* **Added a new command to the Platform... This allows the creation of a Rank or Mine based upon a ModuleElement.** -That has major impact on added flexibility, and could lead to an automation of generating mines and ranks. - - -* **Storing the rank commands within the PrisonRanks class.** -The allows internal access to the commands so they can be used internally too. Will be used for automation purposes. - - -* **Linked the various mine and rank commands to their respective managers** -so they can be easily accessed programmatically now. - - - -* **New Feature! Virtual Mines!** -Now able to create virtual mines. A virtual mine does not exist yet since it has no location, but you can configure all of the options first before setting the area with /prison set area. -This is phase 1 of this new feature. Not fully tested yet. -The intention is that when you auto configure all your ranks, it will also auto configure all your mines to go with those ranks. Then you can go back and set the mine's area as you build them. - - -* **Links the rank command commands to the rank commands so they can be used together.** -Setup createRank to return a boolean to indicate if the rank was successfully created. This will allow programmatic internal use of createRank to automate more features such as rank configurations. - - -* **Add mine commands to add ranks to mines, and to remove ranks from mines.** - - - -* **Added mines and ranks to the /mines info and /ranks info commands.** - - - -* **Added to the platform the ability to link mines with ranks.** -Individual ranks or mines cannot perform this action, but going through the platform can. - - - -* **New Feature! Added _/ranks setup_ and _/prisonmanager setup ranks_ commands.** -Now you can setup your default ranks in the default ladder with a command without -adding them manually for the first time, this command will add all Ranks from A to Z -and their rankupCommands executing the command that your permissions manager uses to add -a permission to the player to access to the `/mines tp ` command, the mineName -given by the permission have this format `mines.tp.` so you should make your Mines -with the same name of the rank, you can edit the `mines.tp.` for to another you want, like -`essentials.warps.` in the _guiconfig.yml_. -The supported permissions managers for now are: -- Ultra Permissions -- LuckPerms -- PermissionsEX -- zPermissions -- PowerfulPerms - - -## tag v3.2.2-alpha.5 - 2020-10-13 - - -* **New Feature!! Added new 20 new blocks to the old block model.** - v1.10.x: structure_block, magma_block, bone_block - v1.11.x: shulker_box - plus the 16 other colors that are available. +* **SellAll auto toggle permission**, added the ability to enable or disable a permission in the SellAllConfig.yml for the full inventory SellAll auto per-user toggleable. - -* **Bug fix: Prevent a NPE when no rank is assigned to the mine.** - - -* **v3.2.2-alpha.5c - 2020-10-13** Important bug fix. Need to bump alpha version soon. - - -* **New Features! Added 48 v1.12 blocks and 44 v1.13 blocks!** -V1.12 blocks: 16 colored glazed terracotta, 16 colored concrete, 16 colored concrete powder. -v1.13 blocks: 10 coral types, 10 coral block types, 10 coral fan types, and 10 coral wall fan types, cave_air, void_air, blue_ice, and bubble_column. - - - -* **Upgrade XSeries from v7.2.1 to v7.5.4** - - -* **New Feature!! Added the first Prison API components** -Started to add some api end points to make it easier to access some basic internals -without having to figure out how to conform to prison's restrictions. - - -* **Continuing work on linking mines and ranks...** -Mines and ranks are now being linked together upon server startup. -Not finished. There are still items to be added, like the mine and rank commands to work with adding and removing ranks and mines. - - - -* **v3.2.2-alpha.5 - 2020-10-11** - - -* **Cleaned up and standardized log levels.** -Added PLAIN for use with mine resets, and DEBUG too. Eliminated redundancies. - - -* **tag v3.2.2-alpha.4 - 2020-10-08** -Had to bump this to alpha.4 due to the new mine sortOrder being set to -1 if -the value is not found in the save files! This may cause users to panic. - - -* **New Feature: Initial work in linking Mines and Ranks.** -This is just the initial framework for the final product. Ranks have not been modified yet. - - -* **New Feature: New Feature: Add a warning if PlugMan is detected.** -It notifies the user that prison will not behave well and can be corrupted if PlugMan tries to reload it. -Also states we are not responsible for any corruption, nor are we obligated to help recover from said corruption. - - -* **New Feature: Added ability to send the ChatDisplay object directly to console log.** - - -* **New Feature: Added /ranks ladder moveRank** -since most people don't realize they can remove a rank from a ladder (it is not deleted) and then add it back in to another place within the same ladder, or another ladder. -This new feature just calls /ranks ladder remove and then /ranks ladder addRank. Simplifies the process and makes it clear to the user that the option is there. - - -* **Eliminated the listing of placeholders from /prison version** -since it was getting to be a really long list. -Provided a reminder on where to find the placeholders. - - -* **BUG FIX!! Found that the default value on mine sortOrder was being set to -1 instead of zero.** -This will suppress all the mines, but nothing will be lost. This value will be set upon initial -loading of the mines if they did not have that value set previously. - - -* **v3.2.2-alpha.3 - 2020-10-07** -Bump to v3.2.2-alpha.3 due to significant update to the Vault integration. -Have not heard anyone else has had issues, so may hold off on releasing v3.2.2 for a few days to add more updates. - - - -* **Bug fix: Had to make changes to which functions Vault is using based upon Vault's version.** -It appears like formerly deprecated functions have been disabled and does nothing now. -Made changes to inspect the version of vault that is being used, then properly target the correct function so it works properly with all versions of vault, including pre v1.4.0. -This bug fix is potentially a critical bug fix and may warrant publishing Prison release v3.2.2 to take care of this issue. - - -* **New feature: Added the player's current balance on the command /ranks player.** - - - -* **Bug fix: Found that the wrong amount was being refunded to the player when doing a /ranks demote with a player_refund.** -Works now, and the log entries are also correct. - - -* **Space missing in the display of the default rank for the command /ranks list.** - - -* **Bug Fix: A config file was being loaded many times to build one gui page.** -Moved the config to a class variable so it would only be loaded once. -This reduced the opening of a 39 mine GUI from 5.5 seconds down to 6 milliseconds for the offending function call. - - -* **v3.2.2-alpha.2 - 2020-10-06** - - -* **Updated the sorting of mines to simplify the sorting.** -Now the sort types either include or exclude the mines. There are no sort types that include all mines. But the function that performs the sorting based upon the sort type returns a collection that contains the included mines (sortOrder >= 0) and also a second collection that contains the excluded mines (sortOrder == -1). -The returned object, PrisonSortableResults, has helper functions to simplify integration in to the /mines list command. -The /mines list command now shows how many mines are included and excluded in that listing, and identifies what the other sort types will display the suppressed mines. - - - -* **New Feature: Setup the complex sorting on mines.** -Mines can now be assigned a sort order, with even suppressing mines from being included in the output. -Mines list can now be sorted in six different orders: alpha, active, and now sortOrder (user defined order), all of which suppresses mines with a -1 for the sort orders. Plus those but with including the suppressed mines. -The default being sortOrder, but if no mines have been configured, then they all will have a sortOrder == 0, and then all will be sorted alphabetically within that grouping. -Changed the prison's GUI to display mines in the sortOrder, with suppression of the -1 sortOrder values. -Added a junit test to test the generated sorting orders since they can be rather complex and should be tested at compile time that they are correct. -Note: In adding this new sorting, found where the bug was where the actual internal sort order was being altered. This is no longer the case and is fixed. + +* **SellAll Sell Multiplier Permission**, added the ability to give multipliers to players by adding to the user +the permission prison.sellall.multiplier.valueOfTheMultiplier here, example: prison.sellall.multiplier.2 will add a 2x multiplier to the 1x of the default, so the total multiplier will be 3x, this multiplier system will add to the existing multipliers. If you give player 2 or more permission multipliers, they'll be added to the default multiplier within the sellallconfig.yml. If any multipliers have a total value of zero, then the player will receive no money. Example: GABRYCA has prison.sellall.multiplier.2 and prison.sellall.multiplier.3, along with a default value one of 1, then the total multiplier will be 2+3+1=6x. As a result, if GABRYCA sells one COAL that has a value of 10, then with the multipliers applied it will result in 60 cash. -* **New Feature: Added Mine Tag Names and 8 new placeholders to support them.** -This is required for the future changes to support linking mines and ranks. +* **SpigotPlayer: added a function to get a list of all perms the player has, and also a function to filter by prefix.** -* **New Feature: Rename Mines. Bug Fix: Delete Mines.** -You can now rename mines. -This also fixes an issue with not being able to delete a mine: It deletes successfully, but is still active in memory. +* **Changed the MineBlockEvent to have an inline mode and sync mode to run the given commands.** +Changed around the save and load for the BlockEvent to support these changes.** -* **Prison_v3.2.2-alpha.1d.jar - 2020-10-01** +* **Added the ability to remove a ladder from a player** +using /ranks set rank help using the rank "name" of -remove-. -* **Bug fix: change how /ranks list works with perms.** -Should allow all players to use this command since no-perm players can use /ranks and that just redirects to this command. -Removed admin features unless player has the ranks.list perm or they are op. The admin features are links to other internal commands. +* **3.2.3-alpha.10 2020-12-14** +* **Bug fix: BlockEvents were not being submitted** unless there was more than one command that was being ran. -* **Potential bug fix if a config option does not exist** -Reformatted so the code will have a better chance of fitting on the screen without a bunch of horizontal scrolling... -plus got rid of a few instances of Objects.requireNonNull() which throws exceptions, which are not being caught. Which is also the wrong behavior to what we need here... if those configs are null, then instead of throwing exceptions, just move on to the next conditional in the if chain. -Should probably never use Objects.requireNonNull since it will crash prison and prevent intended functionality. This should probably be removed from elsewhere. +* **For the BlockEvent commands, disabled async mode** +since the it will submit an async task to run in the future, then it will try to run a sync dispatch command and will fail. So impossible to run commands async. -* **New feature: Gui Languages Support** -New languages folder containing the GUI and future languages files so players can edit them or contribute to make a new -one with translations to download and put there, then you can select it by editing in the `config.yml` the `default-language:` -to the language of your area, this's also related to the file language name, -for example the name of the GUI messages file should be `GUI-en_US.yml` by default, so if you translate to another language -(for example italian) you should rename a new file to `GUI-it_IT.yml` and edit in the config.yml the string -`default-language: en_US` to `default-language: it_IT`, if you select a language file missing in the folder or invalid, -it'll be generated anyway using the default config as the model so it won't break the plugin, then you can translate it -later or edit the config to the correct one. +* **Added a new feature to this config: a List of String values.** +Appears to work, but not yet hooked up to anything that would use it yet. Needs more testing too. +The intended purpose of this is to provide dynamic blocks lists for auto features. -* **Prison_v3.2.2-alpha.1c - 2020-10-10** +* **Added SellAllAuto per-User toggleable**: the instructions to use this feature are on the SellAll Guidebook, + the user will be able to enable or disable the sellAll auto on its own by running the command `/sellall auto toggle` if + this option's enabled in the `SellAllConfig.yml`. -* **Found an inconsistency in how the ranks are dealing with the document engine.** -Mines do not throw exceptions, but they were within ranks, which is not needed. +* **3.2.3-alpha.9 2020-12-12** -* **New feature: added some new 1.14 and 1.15 blocks** -Added some more new blocks since some of the 1.16 blocks appear to work in most circumstances. -Use at your own risk. -These blocks may not properly be spawned and may not be all blocks available for these versions. -v1.14 : BAMBOO, BAMBOO_SAPLING, BARREL, BELL, CAMPFIRE, CARTOGRAPHY_TABLE, COMOSTER, -FLETCHING_TABLE, GRINDSTONE, JIGSAW, LANTERN, LECTERN, LOOM, SCAFFOLDING, -SMITHING_TABLE, SMOKER, STONECUTTER, SWEET_BERRY_BUSH -v1.15 : BEE_NEST, BEEHIVE, HONEY_BLOCK, HONEYCOMB_BLOCK +* **To fix the reported issue of smelt and blocking always being performed when auto pickup is enabled**, changed the hasPermission to isPermissionSet so OPs will not just blindly trigger these features. -* **Added a few v1.16 block types.** -Not sure if they will actually work. Obviously will never work with mc versions < 1.16. Use at own risk. -ANCIENT_DEBRIS CRYING_OBSIDIAN NETHER_GOLD_ORE BASALT POLISHED_BASALT -NETHERITE_BLOCK BLACKSTONE POLISHED_BLACKSTONE CHISELED_POLISHED_BLACKSTONE -NETHER_BRICKS RED_NETHER_BRICKS CRACKED_NETHER_BRICKS CHISELED_NETHER_BRICKS -CRIMSON_PLANKS WARPED_PLANKS STRIPPED_CRIMSON_HYPHAE -STRIPPED_WARPED_HYPHAE NETHER_WART_BLOCK WARPED_WART_BLOCK -LODESTONE QUARTZ_BRICKS RESPAWN_ANCHOR SHROOMLIGHT CAMPFIRE SOUL_CAMPFIRE -SOUL_LANTERN SOUL_TORCH SOUL_SOIL TARGET TWISTING_VINES WEAPING_VINES +* **Some adjustments to the BlockEvent task submission.** -* **Fix: Changed nether_brick to an item** - since this is an item and not a block. Added support so if it is found in a mine upon server startup, it will change it to a double_nether_brick_slab. +* **Change MineBlockEvents to submitted so they do not run in the same process as the block break event.** +It was causing lag, and now its much better. +Also added async submission. And the player can add more than one command per task. -* **Prison_v3.2.2-alpha.1b - 2020-09-29** +* **Issues with ItemMeta not working correctly with auto features.** +Need to do more testing to see if this works, but initial tests are not looking too good. -* **Bug fix: Prison was allowing the material REDSTONE to be added to mines.** -This caused a failure during mine resets since that is not a valid block. That is redstone dust! -Fixed it so upon server startup, it will auto detect the use of this item in mines and convert it to REDSTONE_ORE. Thus the mine will work and won't disable the mine. -Also I changed the BlockType to Item so it's still there, but it cannot be presented as a block in the /mines block search tool. +* **Bug Fix: fixed issue with calculating and applying the durability.** +Turned out there were a few issues, but mostly after the durability was set, the itemMeta was not being resaved to the tool. +* **3.2.3-alpha.9 2020-12-08** Version increase. -* **Set new version to v3.2.2-alpha.1** 2020-09-27 +* **Broadcast rankup messages changes:** +Disabled white text by default of prison Broadcast for now, they'll be again available in the future when + we'll update the lang support. -## tag v3.2.1 - 2020-09-27 +* **Start to setup the ability to use auto features outside of the mines.** +It's not fully enabled yet, so this won't work if it is tried to be used. -* **New Release!! v3.2.1 published!!** -Bleeding was pulled in to master branch. And published to spigotmc.org too. :) +* **Able to dynamically toggle a debug mode to dynamically control logging at the debug level.** +* **Had a few issues with players modifying the contents of the save files for ranks, mines, etc, and the result was invalid json which would fail to load.** +These failure would not normally be encountered if using Prison's commands. Due to amount of time chasing down bugs that don't exist, I added this catch statement to catch malformed json and then generate an error in the console. -## tag v3.2.1-alpha.20 - 2020-09-27 +* **Fixed the links to the add and remove blockEvent commands.** +Had a space in there from an earlier version. -* **Fixed issue with sorting of the mine name in the gui.** - They are now strictly by alphabetical on the mine name. +* **Bug with the saving of the world name** Parenthesis were not used correctly. -* **New Feature: Custom sorting of mines, ladders, and ranks.** -Currently mines and ranks are alphabetical in sort order. -Ladders sorts default first, prestige last, and everything else is alphabetical between them. -The PrisonSortableLaddersRanks will first sort ranks by ladders, then within each ladder, they will preserve the ladder rank order, then all ranks that have no associated ladders will be sorted alphabetically and added to the last of the list. -This new feature has not been hooked up yet to any interfaces, but it's ready. -Need to add mines, but right now there is no way to link mines to ranks. +* **Fixed an issue with the lore being "set" when it really wasn't.** +This was forcing the auto block and auto smelt to be used, and also probably auto pickup too. +* **Corrected a typo in an add message on the add BlockEvent** -* **Bug Fix: Prevent mines from being created that have spaces or no names** -A bug was found where the admin was able to create a mine with the name of two spaces. Changed create mine function to disallow any spaces within the name, or an empty name. Also setup the parms to "require" a name, but not sure if that will work correctly. If it does, then there will be multiple layers of protection to prevent spaces. +* **SellAll fix** +Fixed the sellAll sell bug, it wasn't updating the configs when it should've, now it'll update (even if less efficiently than +before) and it's working. -* **New Feature: GUI Works with Spigot 1.8 now!** -Prison's GUI now works with spigot 1.8. +* **3.2.3-alpha.8 - 2020-12-08** -* **New Feature: The command /prison now includes all other root commands!** -When the command prison is used, it shows a list of all sub-commands. Now it also includes all other Prison registered root commands so the uses do not have to guess what other commands are available within prison. This will provide a listing so they can explore others. -Also disabled the prison troubleshoot command since its not of any benefit. +* **New Feature: Mine BlockEvent Commands!** +Now define events to run on block break events within a mine. Each BlockEvent has a chance and an optional permission. The chance is based upon a range between 0.0000 and 100.0. One command will be chosen out of many that may be defined for the mine. If a TokenEnchant explosion event is handled, then for each block broken it will try for a BlockEvent, so an explosion event could produce multiple BlockEvents. These commands are able to use {player} and {player_uid} within the commands. -* **Moved the spiget project in to the prison project's class path** -Move the spiget in to the project's directory with shadowJar since there has been a few issues with the build. +* **3.2.3-alpha.7 - 2020-12-07** -* **New Feature: /mines tp Can Now teleport players within a rank command** -Allow only admins or console commands or rank commands to teleport someone by name. -This allows rank commands to use this to teleport a player when they rank up. +* **Bug fix: Fixes a bug that prevents comparison between ItemStack and SpigotItemStack objects, which should be equalable.** +One of the side effects of this bug is the failure of the selection wand to be used since it was not able to able to identify that it is actually a selection wand. +* **A strange error was found where a virtual mine has its area set, that it fails to load when restarting the server.** +This situation appeared to be related to the world name not being correctly saved and as such, when reloading the mine, it would result in a failure to initialize the mine. Actions were taken to try to ensure that if the mine is corrupted in memory, then it is still able to be saved correctly so upon loading it is no longer corrupted. -* **Alpha 20 - 2020-09-16** -Yeah. I know. Alpha 20 and not beta! -But many releases have happened under Alpha 19 including some bug fixes. This is incrementing to help ensure when someone grabs the most recent, they know if they have the most recent. -Beta will follow shortly, but there are still a few more additions and adjustments. +* **Found an issue that when a custom blocks plugin is added, used, then the plugin is removed while the blocks are still defined in the mines.** +It was resulting in nulls for the integration handling. +This deals better with the loss of the integration so it does not cause problems. -* **Tweaks to auto manager** -Found duplication on durability processing. Eliminated the duplication, but now it will only be applied when auto pickup is enabled. Not 100% sure if that is the best logic, but figuring if prison does not handle the block break event, then do not apply the durability. -May have to revisit and tweak how smelt and blocking is working too. -Changed the ALL pickup to be the first processed since that is probably going to be the most common situation so bypass the many block checks to save some CPU time. +* **Fixed a few issues with blocks returning null PrisonBlocks, or at least deal with the null blocks better.** -* **Attempts to force the plugin's config.yml file to be reloaded** -It "should" work, but it does not. -Keeping this code since I will expand upon it and get it working, even if I have to go outside the bukkit handling of that file. +* **Attempts to better handle exceptions when running the commands.** +So far, without being able to produce many failures, it does not appear like this is capturing any exceptions? Will have to wait and see if it is able to provide better error messages. -* **Bug fix: Duplication of mine blocks. Only impacts more recent Alpha.19 releases.** -Duplicate blocks are now "fixed" when loading a mine. If a duplication fix is applied, the fixed mine data will be saved and a message will be shown that an inconsistency was detected and fixed. -Overall this did not cause any crashes or corruptions of mines, but it did duplicate internal data for the blocks associated with a given mine. -Symptoms were loss of air blocks (if you had an air percentage) or if enough blocks were duplicated, the GUI would give you an error message indicating there were too many blocks and it could not display them all. -The issue was initially thought to be related to a lambda function, but that was rewritten and confirmed that it wasn't there. The issue was ultimately tracked back to a typo on the new block handling. So this would have only impacted the more recent alpha.19 releases (not all). +* **Major changes to the Auto Manager to remove as much bukkit/spigot specific code as possible** +since that will be limiting support for custom blocks. This is the first phase of changes, and the change to support custom blocks will come later. +Due to the major changes that occurred, there could be bugs so an alpha release should not be generated without more testing. -* **New Feature!! A Reset Threshold Percentage has been added.** -Before the reset threshold was set to zero blocks. Now, if enabled, it will reset the mine at another predetermined percentage of blocks remaining. -A value of zero disables this feature since that is the same as a zero block reset. +* **Changes to some of the functions in the compatibility classes to prepare for changes with auto manager.** -* **Changed mines placeholder for time remaining formatted** -Dropped the decimals since it does not look good when updating every second or less. +* **Additional functionality and changes in the way block related things are used and processed.** +This is preparing for changes to auto manager. -* **New Features! PLAYERMINES placeholders!! Added 24 new placeholders including aliases!!** -These placeholders are a hybrid between player and mine placeholders. These placeholders can only return results when a player is actually within a mine, and these are the mine's stats. In other words, whichever a mine a player is in, it can show all of that mine's stats. -This will not work in holographic displays since they are not associated with any players. It will work with chat prefixes, but these are stats you generally don't want as chat prefixes (maybe just the mine's name?). -But where these really can be awesome is used in the player's scoreboard. So when they hop in a mine, they can pull up in their scoreboard stats on the mine itself. +* **SellAll Material support** +This should make sellall support all material, from legacy to 1.16 (all XMaterials). + +* **SellAll signs** +Added the ability to make SellAll signs. +The **sign** should have the **first line** as `[SellAll]` to make this works, also when clicked it's + Just a shortcut to the **/sellall sell** command, very simple (also to use the sign you must RIGHT CLICK IT). + - To create a sign you need to have the permission`prison.sign`. +This feature needs to be enabled from the `config.yml` +by editing or adding (if missing you should add this line manually or delete the config, then +restart the server) this like from: +`sellall-sign: false` to `sellall-sign: true`. +It's possible to edit the tag of the sign when generated from the `config.yml` by editing this: + - `sellall-sign-visible-tag: "&7[&3SellAll&7]"` + +* **SellAll AutoSell** +Added the ability to enable the autoSell, autosell's a feature (also needs autoFeatures to be enabled and AutoPickup) with + the goal of triggering the SellAll command when the player inventory's full. + You can enable this feature from the SellAllConfig.yml and by default's disabled, to `enable` it + just turn edit this under the Options config section from `Full_Inv_AutoSell: false` to `Full_Inv_AutoSell: true`. + It's also possible to enable or disable a notification telling the player that the AutoSell got triggered, by default + it's under the Options section sellAllConfig.yml section like this: `Full_Inv_AutoSell_Notification: true`, to disable it + just turn it to `false`, you can also edit this message by editing the Messages en_US.yml at this path `/module_conf/lang/`, + in other worlds you can find the messages config en_US.yml in the Prison folder, then open the module_cong and the lang + folders, the line to edit's under the `Message` section with the name of `SellAllAutoSell`. -* **Bug fix: Placeholder progress bar configs in config.yml not working** -This addresses some issues with being able to load the placeholder progress bar configs from the config.yml file. -Ran in to issues with symbols not being quoted. Strings normally do not have to be quoted, but yaml was interpreting them incorrectly and was trying to treat them as special values. So quoting prevents that. -Also had unicode characters in the comments which also may have be causing issues indirectly, so removed them. +## tag v3.2.3-alpha.6 - 2020-12-04 -* **New Feature! Placeholder progress bars!** -prison_rankup_cost_bar, prison_rankup_cost_bar_laddername, prison_mines_timeleft_bar_minename, prison_mines_remaining_bar_minename, plus their aliases. -This adds a configurable progress bar to the list of placeholders. The /plugins/Prison/config.yml file can be reset to load the parameters to customize the progress bars. For now, if the configs do not exist, they will fall back on to the default values. +* **Setup modules to have a deferredStartup() function.** +This allows code that is dependent upon other integrations to be ran after the integrations are fully setup. +Mines have to load after the integrations are loaded due to the new block model and specifically the new support for custom blocks, which means all custom block integrations must be loaded before anything tries to use the blocks, such as loading of mines. +Placeholders have to be reloaded after the deferredStartup() function is finished. -* **Minor fix: Found that some placeholder key values were not being generate with all lower case characters.** -This could have resulted in problems if the users were trying to use all lower case. -Also provided a placeholder flags exclusion filter to remove the wrong compound types within mines. +* **Disable unused code dealing with MinesPlayer and the auto pickup and smelt and block within the Mines module.** -* **Minor improvement to placeholder search when using Players** -Added player information when it's supplied with the placeholder search. This provides important feedback to the user that the supplied player is valid. -* **Bug fix: For the PlayerManager was not allowing PlaceHolderFlags types of LADDERS to be processed.** -So ladder based placeholders were not being translated correctly (sometimes they were). This was fixed. +* **Setup the file I/O to be specifically UTF-8 enabled.** +The old file I/O would default to the platform defaults, which may not have been UTF-8. This code has been tested and works with UTF-8 encoded characters, although Prison is unable to display them. It is unclear if this is a limitation of Prison or Spigot. This has been tested with Spigot v1.8.8, v1.12.2, and v1.13.3. The test consisted of directly adding a UTF-8 character to a rank save file with a utf-8 compliant editor (not WordPad), starting the server, making a change to the rank to force a save with the new data, then inspecting the contents of the new rank file to confirm that the utf-8 character is still encoded as utf-8. All tests were successful. Future work will be done to see if there are any other ways to enable it, but for now, at least the file I/O has been fixed and proven to be good and working. -* **Eliminate the obsolete message and .meta checks.** -This version of prison cannot perform any updates on the old obsolete versions of data. That functionality was removed prior to the v3.1.1 release. To upgrade from v2.x they will first have to upgrade to v3.0.0 and then to the current release. +* **v3.2.2-alpha.6 - 2020-12-01** +* **Added UUID to the player look up options which hits the bukkit offline players.** -* **Move the player mine cache to the PrisonMines object** -This will allow it to be accessible from other areas within the prison plugin. This will need to be used with more advanced placeholders that will be added shortly. +* **Added a logPlain function to the platform that bypasses color code translations** and removal. Used for debugging situations. -* **Enhancement: Optimize the generation of placeholders** -OPtimizing placeholders by eliminating the generated placeholder that lacks the prison_ prefix. Instead, adding the prison_ prefix to all identifiers that are lacking it so it can get a hit on the real entry. Fix the display of the stats... was calling wrong function. +* **Minor changes to address some issues with the new block model.** +For MineReset.resetSynchonouslyInternal() the way the Block is created to a variable now, eliminates a lot overhead since it was being called multiple times, of which it has to go through the construction of that object each time. So it should be better performance this way. -* **New Features! Added 4 new placeholders - Cost Remaining** -These pertain to cost remaining for rankup. -prison_rankup_cost_remaining, prison_rcr, prison_rankup_cost_remaining_laddername, prison_rcr_laddername -Now you can count down the amount of money needed for players to rank up! Remaining value is never negative, but it shows zero instead. +* **More updates to better support block break events for custom blocks.** +Not yet hooked up, but getting there. -* **Few Feature! Reload Placeholders** -Provided a reset function for placeholders. The new command is registered twice to provide the most flexibility. -**/prison placeholders reload** and **/prison reload placeholders** +* **Changed the name of a block from pillar_quartz_block to quartz_pillar so it would be supported in both XMaterial and the old prison's BlockTypes.** -* **Realigning source for Spigot Placeholder code.** -Moved a ton of placeholder code to the tech.mcprison.prison.spigot package to get it out of the SpigotPlatform class. -There was way too much business knowledge being exposed within SpigotPlatform and wanted to group it all under a placeholder's package. -The real meat of placeholders has to come together within spigot because core has no knowledge or access to the mines module, or the rank module. -This required creating a new interface and pulling the majority of the functions out of the Platform interface. +* **Fix the way DoubleArgumentHandler and DoubleClassArgumentHandler deals with replacement of the $ and % symbols.** +Needed to use replaceAll() instead of replace(). -* **Change in SpigotListener to use the singleton that already exists** -Changed to use the singleton instead of the passed object. Cleaner. +* **Updates to the /sellall command** +Hooked /sellall up to the prison command handler. -* **Bug Fix: Fixed a mine's block type loading issue.** -The blocks are now checked against a greater range of possible values to improve match rates when reloading mines. -If a block cannot be mapped, then an error message is now printed to the console so it can be addressed. -There was an issue with QUARTZ_PILLAR not being able to be mapped back to the correct block type. +* **Expanded the command handlers to include more types** to allow a greater variety of parameter types on all prison commands. -* **New Feature: Add the internal placeholder counts on startup.** -These counts are the total generated placeholders and some placeholders have more than one key. +* **v3.2.2-alpha.5 - 2020-11-29** -* **New Feature: Added reset notification permissions** -Now only players with the mine's permission can be notified if the feature is enabled. -This setting is on a per mine basis, and the permission used is displayed in the /mines info listing. +* **Bug fix: Tried to reset a mine with over 400,000 blocks** +and ran in to issues. Had to set a delay of one tick when resubmitting the next page of blocks. Works fine now, but the one tick delay does add to the overall time, which is not bad considering. -* **Admins and console are able to view player's past names with /ranks player** -When admins and console use `/ranks player` command it will show past names for all players that have more than one name recorded. +* **More enhancements to hook up custom blocks and enabling the new block model.** +Have them loading and being added to the PrisonBlockTypes as valid blocks. Also hooked up to be used with block search and can be assigned to the mines. These custom blocks are also being saved. -* **This implements the tracking of the player's name** -This now tracks and detects when player names are changed so it can record the change. -This is passive in that it does not try to actively detect name changes unless the player is active within the prison and using features that require the use of the player ranks and associated details. -Offline players will never have their names updated if they are changed and they never return to prison. It is possible that a player could change their names a few times and if they do not log in to prison, then it will not be able to track all the interim name changes, only the current name they just logged in with. +* **Changed the offset time from seconds to milliseconds.** +Enabled the config.yml setting prison-mines-reset-gap. This will allow better tuning of the mine gaps, but could cause server lag problems if the gap is too small. -* **Setup the internals for tracking the blocks mined for each player** -Established the core internals on tracking blocks mined per player. Nothing uses this yet. +* **Changed Pgd to Paged so it makes more sense in /mines list.** -* **Add support for recording player names within the RankPlayer.** -This will help admins manage their data especially if they have to work with the raw data. -Multiple names can be tracked, with the last name in the list being the current name. Players can change their name numerous times and always go back to the same name multiple times and this will record them. -This only establishes support for names, but this commit does not get the actual names. This update is able to save and read the data from the saved file. +* **Clean up placeholders list.** +Very few placeholders are able to be shown on the same line as another. So eliminate the code that is trying to add to same line. This also makes it more difficult to find a placeholder. -* **Enhanced the /ranks info details** -Changed around the /ranks info to show the actual rank name and tag so it's obvious. Also moved the player count outside of the admin block so all players can see it. +* **Fixed an issue with the logic statement when using RankPlayers for substitution of offline players** -* **Added GUI Compatibility interfaces and support classes** -Restructure the compatibility classes to separate the blocks from non-blocks and added in GUI support. -It maybe a little odd how the interfaces extend from other interfaces, but the chaining allows separation of functionalities to keep the code cleaner at the interface and implementation layers. +* **Updated a few documents** +Added a document on setting up Vault. Added more information on how to reload the placeholders in a few documents. Added a few screen prints. -* **Alpha.19 - 2020-09-08** -Final alpha version prior to beta! Yeah I know I said that before, but I did not expect so much awesome stuff to be added! Need to have a clean transition to beta, so this has to happen first. +* **Prison's placeholders are now fully registered on PlaceholderAPI's wiki** +Prison still dynamically registers its plugins upon startup because everyone has to be generated and expanded. -* **New Features: Show all ranks and player counts upon startup and on demand** -For each ladder, all ranks with the number of players at each rank is now displayed at startup of the plugin. -Also a new command was created to be able to display this information at any time. The command has the option to change the parameters to fine tune the results. The command is /ranks players. -When the rank of a player is viewed, it is now displayed to the log. An admin reported that all ranks were changed on their server, but no transactions appeared in the logs. It was shown in the logs when players checked their ranks, but it is unknown what thoes ranks were. SO this tries to record that. +* **Bug fix: Found a couple of placeholders were mis-configured. ** -* **New Feature: Language files are written to the prison's plugin directory by defaul** -If the language files do not exist at startup, then they will be written to the proper lang directories. This helps admins find the files and edit them without having to try to pull them from the jar file. -The core module, which is not a true Prison module is now correctly being remapped to the /plugins/Prison/module_conf/core/ directory for all language file uses. This keeps things consistent and clean. -The normal use case is that the jar file language files will be loaded first, then the external files will be loaded and replace any key value pairs that may have been loaded previously. -Warning... the language files ignore the package names and goes strictly by the key value in the files. Therefore if the same key exists in more than one language file, then the last one loaded will replace any other previously loaded values. -This has been tested and it works great. No new mapping have been added. +* **Upgrade Cryptomorin XSeries to v7.6.0.0.1** -* **Added a unique permission for /rankupmax so it can be disabled.** -Its `ranks.rankupmax.[ladderName]` but the player must also have `ranks.user`. +* **v3.2.3-alpha.4 - 2020-11-27** -* **Added more details to Ladder save files** -Added Rank names to the ladder's save file. This will help figure out what is what and could help eliminate possible errors. If a ladder is loaded and a name is added, then it will flag the ladder file to be resaved after being fully loaded to ensure the contents of the file is up to date. -No one should ever make manual changes to these files, but this at least give more information due to the use of the magic numbers with the rankIds. -Added a link to the actual Rank object to simplify the use of the objects. +* **Bug Fix: Fixed a typo on enabling prestiges based upon the config.yml setting.** -* **New Feature: Broadcast Rankups and Demotions** -There is a now a new feature that will broadcast to the whole server when someone gets a Rankup Or a Demotion. -This can be disabled within the config.yml file. If the entry is not there, it is the same as if it has a true value. Any other value is considered false. +* **For prestige this gets rid of the requirement that perms exist for the player to use prestige** +the rankup on the prestige ladder. All that is needed is to have prestige enabled in the config.yml -* **Alpha.18 - 2020-09-01** -Final alpha version prior to beta! +* **Simplify some of the rankup code so it's directly using rankNext and rankPrior.** +Get rid of some optionals to simplify the code too. -* **New Feature: Mine Reset Paging** -Finished hooking up the paged mine reset code. And it works too! Tweaked some of the timing settings such as milliseconds and block thresholds which will better tune this to be more responsive to paging. -Had to add comparable to the MineTargetBlockKey for the map to work correctly. -To enable use `/mines set resetpaging help`. +* **Significant change: RankPlayer now extends from the Player interface.** +This allows using RankPlayers when cannot get an OfflinePlayer so admins can perform more function on players when they are offline. For example promote and demote. +This resulted in some major internal changes on how RankPlayers are tracked and managed. -* **Bug fix: Correctly using magic values with XMaterials** -This fixes the usage of the magic value with bukkit/spigot versions prior to 1.13. The issue was that the only way to set the data value was through the BlockState and I did not force the update. Now the block type and rawData are being set only within the BlockState and then the update is forced. This resolves the issue and should work for all block types that rely on using the magic values. -The way the mapping to the XMaterial was changed to try use the name matching first since they have a high correlation. Also the the legacy matching is the last resort now. +* **Rank up commands were using a misleading generic RANKUP_FAILURE** +which had an associate error message that was misleading and was reporting that there was a failure with reading or writing data and that the files may be corrupt. +Such a situation was not true. Added other error messages to better explain the situation. -* **Added v1.16.1 now officially supported and added to the test environments** -Working fine. No issues found. Now have a working v1.16.1 environment to test from to ensure issues are addressed. +* **Hook up the new Custom Items integrations and tie them in to the prison new block model** +so if the the Custom Items plugin is active, it will automatically add the custom blocks to the available list of block types. +This is working and the custom blocks show up in the block search. -* **Reporting for supported block types** -Added a raw spigot/bukkit test to round out the test to see how many blocks are available to prison. -Running this test on any version should give a fairly accurate idea of how many more blocks are gained with the newer versions of spigot. -Pre 1.13 versions of spigot cannot be fully tested to identify all possible block types due to lack of ensuring individual Material types with different data values within the ItemStack cannot be identified as being invalid since that is left for the client software to decide. -This test adds no new functionality, but provides a reporting on how the newer infrastructure will work. +* **Setup a new Custom Block integration type and added CustomItems integration.** -* **More work on new block type support** -Got a lot of the questionable code working better so 1.8.x and 1.16.x will not have problems with class or method not found exceptions. Pushed a lot of version specifics to the compatibility classes. -This does not add new blocks to prison, but lays the foundation and support for new block types. +* **v3.2.3-alpha.3 - 2020-11-23** -* **Major New Feature: Work In Progress! New handling of Blocks and Materials!!** -Starting major changes to how the block types and materials are processed. -This is a Work In Progress! Use with caution until stabilized. -Upgrade the spigot API to 1.13.2!!! -This should make Prison more 1.13+ compatible and support more block types, and transition to supporting all block types that exist for a given version. -Add in the cryptomorin's XSeries to better deal with newer block types. Trying to get rid of deprecated function usage, except for within spigot 1.8 specific code sets. -Finally got lapis lazuli working! So this is heading in the right direction. +* **Fixes to sellall** +Optimization of sellAll and fix of unloaded configs when updated. Fixed configs when edited didn't load with the updated one. -* **Alpha.17 - 2020-07-28** +* **v3.2.2-alpha.2 - 2020-11-23** +Bump version because of a lot of improvements to the new block model. It actually appears to be working very well. Still need to do more testing and will not enable by default for a while. It will have to be an opt in feature for now. -* **New Feature: Sellall has been added** +* **Found a typo in the old block model for weeping_vines** so it was not being recognized. It's working now. -* **Worked on enhancements for the auto features.** -Enhancements and hooking up fortune, silk (does nothing... yet), durability, and additonal drops. -Enhancements to improve stability and quality -Eliminate the switch statements when dealing with Materials since there are a few that cannot be hard coded and instead must use the Material.matchMaterial() function since the type may not exist in all versions. It's also preparing to transition to another way of dealing with materials, but cannot use them until after prison is migrated to 1.13.x. +* **Some fixes to get more of the new block model functional.** +Added some support to help fall back to the correct XMaterial for a few block types such as WATER and STATIONARY_WATER which is not mapping for 1.8.8 because of the data value representing the flow height, but yet, XMaterial is trying to map it to an resource using data (it shouldn't though). -* **Fixing some block types so they are not hard coded.** -Initial setup. This will help transition to 1.13.x which will better position to supporting 1.15.x and 1.16.x block types. -Not all issues have been addressed yet, like the GUI. Want to confirm this is working before expanding. +* **For the new prison block model, when dealing with PrisonBlocks**, it needs to record invalid block types so they can be logged and hopefully fixed. -* **Prevent the default ladders from being deleted** -The default ladder was actually deleted by a user. Could prevent a ton of issues by preventing these from being removed in error. +* **Setup more of the new prison block model to work with paged mine resets.** +Sharing the MineTargetBlock behavior through the use of MineTargetPrisonBlock to reduce complexity and reuse existing structures. Still a work in progress. -* **Enhanced the handling of unloaded modules.** -They were not behaving correctly and causing issues. Also better log the warnings that the module was not loaded. - - -* **Add documentation for Mine Commands** -Added documents for mine commands. Document how to setup a Parent Mine with Child Mines. - - -* **New Enhancement: Mine Commands Enabled and Enhanced!** -Mine commands have been enabled. They have been enhanced by adding the ability to have some commands ran before the reset, or after the reset. This gives a great control over customization and integrating external commands to operate most efficiently with actual block resets. One example is to have a real forest of trees reset and completely rebuilt each time. The other example of usage is to setup up a parent mine to control the resetting of all child mines. - - -* **Alpha.16 - 2020-07-04** - - -* **More Enhancements to AutoManager** -Some refactoring and some enhancements to AutoManager. -Added isCalculateDurabilityEnabled, isCalculateFortuneEnabled, isCalculateSilkEnabled, and lore durability resistance. -Feature enhancement: Permissions added to config file so they can be customized as needed. Added these custom permissions to the /prison automanager command so they always reflect the correct permissions. If changed online, everything reflects the changes right away. The AutoFeatures now are able to record their parents so it makes possible the ability to get all permissions related to a given section. For example all permissions, or all autoPickup permissions. - - -* **Enhance Auto Manager Features** -Still a work in progress, but becoming more mature. -**Added new feature**: Durability able to be turned on/off. -**Added new feature**: Durability resistance is now able to be used as a lore. With no integer value it will have 100% effect and disable durability calculations on the item that has the lore. If less than 100, then it's a percent chance durability will be skipped. -**To do:** Hook up a new block drop calculation and use the new fortune and silk functions. -Removed some hard coded Material types to make it more compatible with newer releases of spigot. -Reworked how lapis lazuli auto block is processed to work with v1.13.x and higher. - - -* **Upgrade the Spigot API to v1.12.2 from v1.9.4** -Prison was built on spigot api v1.9.4 for the longest time. Looking in to trying better support newer block types, had to upgrade the version to something newer. Tried v1.13.2 but it failed to compile. V1.12.2 works well. - - -* **Fixes to AutoManager and new file IO** -Got the new file IO working better since there were a few issues with getting the actual values from the spigot yaml reader. Also made changes to the ValueNode objects to make them easier to use and to be consistent between them all. - - -* **Bug Fix. NEATHER_QUARTZ is not a block** -But its type was set to a MaterialType of BLOCK. It is actually the result of breaking NEATHER_QUARTZ_ORE, of which, that is the proper block type to use. Use of neather_quartz would result in many exceptions in the console, one for each attempt. - - -* **New feature: Moved AutoManager to prison core and out of spigot module.** -This will allow access to these settings in all other modules instead of just the spigot module. -Rewrote the interface on how the the properties are saved and loaded to elimiante the dependancies upon spigot. - - -* **New Feature: Ladder specific placeholders for player ranks** -Add in placeholders for ladders. These are rank placeholders, but targeted for specific ladders. -Enhanced the `/prison placeholders search` to work with player based placeholders, and added support to specify the actual player too so it can work from the console. The placeholder search should now work with all placeholders and will be able to provide values for players if ran in game, or if the player's name is provided within the console. - - -* **Ranks names cannot contain formating** -Made it so new rank names cannot contain & formatting. It causes issues and that's what tags are for. -This change mitigates any preexisting ranks that may have been created with formatting, the /ranks list now escapes the & characters by replacing them with -. Then the /ranks info command is now able to use those escaped names. The results of this change is that new ranks cannot contain & formatting, but preexisting ranks should continue to work and could eliminate issues. -There was an issue with /ranks list and formatted names causing issues with on click events. - - -* **New Feature: Prestige! Significant work on Prestige added!** -Gabryca provided a lot of enhancements and features to the new Prestige system that he has been working on. It was merged with bleeding from it's own branch. It was pulled in because it has reached a point where it can start being used and undergo testing. - - -* **New features: AutoManager perms and lore enabled.** -Players can now use auto pickup, auto smelt, and auto block can be used if they either have the perms (all or nothing) or if the tools have the lore (0 to 100.00 percent chance). -The tool lore supports full enablement (no number following the lore) or a percent chance than can range from 0.001 through 100.000. Allows for tools to gain better chance. -The config setting Options.General.AreEnabledFeatures enables all mines and overrides player perms and lore. Set to false to allow perms and lore to work. -May need more testing, but looks functional so far. -Added new command /prison automanager to just display info on automanager and the perms that will enable it. The command only shows the help. - - -* **PlaceholderAPI Troubleshooting and Tips** -Update PlaceholderAPI install docs to reflect a possible way to get it to work with other plugins when the other third-party placeholders are not working. -At this time, it does not appear like this applies to Prison, but it coud be a tip that could be a solution for an edge case issue that someone may experince in the future. - - -* **Performance improvement in auto manager.** -This change to the auto manager has a significant performance improvement per block break by not having to reload all of the parameters each and every time a block breaks (it no longer loads from the file on each block break event which really reduced the overhead too). -This also sets up the auto manager for the next phase of enhancements. - - -* **New feature: The /mines tp now can be used by players** -If a player has the new permission: mines.tp.[mineName] they can use this command to tp to the mine. -The mine name must be all lower case. - - -* **New Feature: altPermissions on commands!** -Now if there is a permission that is internally checked within a command, it can be reported with the altPermissions so it can displayed if the user does the help keyword. -Examples: /rankup, /mines tp, and /ranks - -AltPermissions are alternative permissions that are not checked internally, or automatically. -It is up to the programmer to put hooks in to the code to check on these altPermissions. -This field of altPermissions is strictly for displaying helpful information to the end users -and it is only helpful if it is included. - -For example the command /rankup has an optional parameter ladderName. If a ladderName is -provided, then it checks to see if the player has the permission: ranks.rankup.[ladderName]. - -Because these permissions are not ever used to check for actual permissions, it is very -important to provide parameters such as [ladderName] to signify where the server owner, or -admin, must place the real ladder name within the permission. - -This is such a critically helpful feature because otherwise the only way you would know -that you need this permission is to look at the source code, of which many cannot do, and -those who can, may not know where to look. So this provides very important information that -was not available before. - - -* **New Feature: Command help keyword now includes permissions** -New Feature: Now includes the permissions in the help commands so users do not have to guess or hunt down what permissions are needed for these commands. - - -* **Fixes ladder commands: delrank and addrank** -Fixes the problem with removal and readding ranks from a ladder. -You can use /ranks ladder delrank to disconnect a rank from the ladder. Then use /ranks ladder addrank to put it back in to the ladder in a new position. - -These changes makes sure that the rankPrior and rankNext are set to null to remove dead or changed connections. It also sorts each ladder before hooking up the those links. - - -* **New Feature: Placeholder tools.** -You can now test all placeholders, including multiple placeholders within one test. -Also you can fully search for any placeholder, either player based or mine based placeholder. If you run the commands from console, you cannot use the player placeholders. -The commands: /prison placeholders test and /prison placeholders list. - - -* **Start the ground work for supporting another integration** -Initial setup for WorldGuard. Ran in to issues with lack of v6.x even existing in maven, which is needed for minecraft 1.8 through 1.12.2. WorldGuard v7.x is for minecraft versions 1.13.0 through 1.15.2. -Also both WG versions appear to use the same package and class names too, so how to include both in the build without conflict? Yeah, not sure. Will have to figure that out too. -Anyway, starting to provide the basic integrations hooks, which are disabled right now, but will be enabled as the details are worked out, and as Prison is adjusted to work better with it. - - -* **Failed Attempt to Enable 1.13 Flattened Materials** -Failed attempt to give 1.15.x the ability to have native block types. This code has been commented out with hopes that it could be used in the future. -The reason why this won't work, is not that the codes entered are incorrect, but it appears like the Material object that is actually being used when running on a Spigot 1.15.2 server is actually using code from Spigot 1.9.2 since none of the 1.13 materials are recognized at runtime. -So the "wrong" classes could be included in the build artifact, which in turns get's used during runtime. But should it? -So for now, its all disabled so it can be revisted later. - - -* **New Feature: Mine commands.** -Added commands to mines. This may be complete, but not fully tested, so disabling so it cannot be used. Will enable when it is proven to work well. -The concept with mine commands, is that after every reset, it will run a set of commands associated with the mine, of which could permit new and complex types of mines. - - -* **New Feature: IGNORE BlockType added.** -Created a new block type that will allow ignoring what is already there. -Ignore can be used instead of air, and as such it will not replace whatever is there. -It is possible that all blocks are 100% ignore so that way nothing in the mine changes during a reset. - - -* **New feature! Two new placeholders: formatted time.** -The placeholders for reset interval and time left now have formatted versions and aliases. -The format is 13d 21h 13m 1.23s. 1h 0m 13.13s. -It does not show leading digits if they are zero, such as days will be suppressed if zero. And days, hours, and minutes will all be suppressed if they are all zero. But if hour is non - - -* **Bug fix: Failure in logging upon plugin startup** -There was a failure on getting and calculating a paper 1.10.0 version due to a period to the left of the primary version. As such, the old code could not deal with it and was throwing a failure. To add to that failure, since it was during start up of the plugin, the resources were not yet setup for to allow the logging to work so that was causing another failure. -This fix allows the output of the log message to System.err so it will be at least recorded in the log files. - - -* **New Feature: Now Supports delayed world loading! Multiverse-core now properly supported!** -New Feature: Major modifications to support delayed world loading. This supports Multiverse-core, and other plugins, that may load worlds. -You cannot use softdepends or hard depends to ensure the world is loaded, but instead must use WorldLoadEvent events. -These changes enables the mines to load even when their world has not been loaded yet. It also disables any function or changes that could corrupt the mine's data by not having the world enabled and loaded. - - -* **Bug fix: Reset Radius Notification not working** -The message notification functions were not using the mine's radius value, so all radius notifications were based upon a distance of 150 blocks. -Extend within notifications to include players standing on top of the mines too. - - -* **New Feature: Start to properly deal with delayed world loading** -Plugins such as Multiverse-core may load most of their worlds after Prison has tried to load the mines. During the creation of the mines, the worlds must exist, otherwise the mines cannot be loaded under the older way prison was doing things. - -This change allows mines to be loaded, but will delay their hook up to the -world until the worlds are formally done loading. - -This is a work in progress and is not complete yet. - - -* **New Feature: New command /rankupMax will rank up the player until they are unable to afford the next rank.** - - -* **New feature: Provided a way to disable the resetting of the mine when reaching zero blocks.** - - -* **New feature: Can now disable the reset when a mine reaches zero blocks" -Provided a way to disable the resetting of the mine when reaching zero blocks. - - -* **Updates to AutoManager: Full Inventory** -Improve the full inventory handling. Basically always try to work with inventory items (auto pickup, auto smelt, and auto block) and if they cannot fit back in to inventory then just drop them. That allows them to fill up inventory slots that may not be full. -Have the dropExtra function use either the specified holographs or the action bar to show the inventory is full message. - - -* **Few fixes to mine commands, rank loading** -Fixed an issue with Mines commands. The one was a typo (had to be a stray space) and the other was using block search before using any other mine command (missed testing that before). Tweak formatting on mines info to make it easier to read. - - Fixed an edge case situation where the next rank was not available. Not really sure what caused it to be missing, but this prevents issues from happening within prison. - - -* **Improve how bypass resets works.** -Fine tune the bypass resets so it works better. Found some issues & fixed them. - - -* **Added 3d distances to some mine related commands** -Added the distance the player is from the mine to the /mines info command. -Created a 3d distance function to use for displaying distances to the mine. -For mine related messaging, its using 2d distances, ignoring the Y axis. - - -* **New Feature; Slime Block Fun!** -Simple feature to add some bounce to the Prison fun! -Different items in hand increases boost. After jumping on a slime block, the player gains immunity from fall damage, but they can still die if they land in lava, the void, etc... -Not really sure what the life span of this will be? -To enable, set the configuration property "slim-fun" to true in plugins/Prison/config.yml. - - -* **New Features: Command /mines list now has paging! Plus useful sorting.** -Major changes to the /mines list command by adding paging and better to read formatting. -Now you can specify a page and be able to read what's in the list. In game you can click to page to other pages. -This listing is sorted by Blocks Mined (since last server restart) then by Mine Name. This help to put the more active mines on page 1 and the inactive ones at the bottom of the list -There is an option for pages of ALL so you can get a full dump. If you want it. - - -* **Minor refactoring: Remaining Time before the Mine Resets** -Moving the calculations for the remainingTime in to the core mine classes so it can be accessed by other functions. This also moves the business logic out of the MineManager and puts it in the mine, where it should be. - - -* **Typo fix: Noticed a field was named "Rest" instead of "Reset".** -The fixing of the name does not alter the behavior of the code, but the wrong name could confuse someone. - - -* **New Feature: New Mine Placeholder! Mines Reset Count.** -Added a new mines placeholder: Mines Reset Count. Identifies how many times the mine was reset since the last server restart. - - - -* **New Feature: Zero Block Mine Reset Delay** -Added a new parameter to mines for a mine reset delay when the mine reaches zero blocks. - - -* **New Feature: Setup a packaged paging system for the commands** -New feature: Created a new class to encapsulate multiple pages for commands. Based upon /mines block search and hooked it up to /mines info. -Provisions for pre-pages that are shown before the listings, such as the first page of /mines info. Will expand to other commands later. - - -* **Bug Fix: If BlockType does not exist use STONE instead** -Bug fix: Found a problem that if you put a Block Type in a mine that does not exist on the server it fails to reset the mine and there really are no errors shown in game. -Default to STONE if the material does not exist. - - -* **New Feature: New Placeholder for mines. Blocks Mined!** -Added new placeholder blocks mined. This reports on the total blocks that have been mined within a mine since the server restart. - - -* **Improved Performance: AutoManager by extending from OnBlockBreakEventListener** -Extend the AutoManager so the same BlockBreakEvent logic for cacheing the player's last mine used to optimize performance. -By extending the class, and creating the doAction() function allows for simple reuse of the event listener. -It is also critical that the AutoManager is able to set a LOW event priority. - - -* **Improved performance: for the onBlockBreak event listener** -This is the code that monitors the number of blocks remaining in a mine. This logic will also be applied to the auto features since it needs to perform the same basic initial setup and checking to ensure the blocks are within a mine. - -Significant improvements to the OnBlockBreakEventListener to try to minimize overhead and to improve individual performance for all players. -The biggest hit, performance wise, will be when mining outside of the prison mines since it would have to check to ensure it's not within a mine, and will go through the whole list. It's just simple math, but performed for each mine that exists so it will add up. -Overall, the overhead is not much, but efforts were made to reduce it as best as possible, of which, I think is the best that can be done with the current environment. -Also renamed addBlockBreakCount function to incrementBlockBreakCount since that's what it is doing. - - -* **New Feature: Hooked up auto mine reset when blocks remaining reaches zero** -When a mine reaches zero blocks left, then it will auto reset. -This is hooked in to the onBlockBreak monitor and all it does is cancels the current mine's reset and then resubmits it to reset. -This could allow for the creation of a one block grinder. Although there may need more work, such as delays to slow down the reset since it is able to reset at blistering speeds. - - -* **New Feature: Enabled the blockBreakCount feature** -Using the new blockBreakCount feature on the placeholders to eliminate the use of the old refreshAirCount() function. -This should provide a lot of performance improvements and will allow for live updates without much overhead on the server. - - -* **Internal Mine Optimizations** -Refactored a lot of stuff with mines to eliminate wasteful operations. -Setup a collection organized by name for quicker access when there are larger number of mines within a prison. -Changed remove block to remove ONLY the first block so as to help admins remove duplicates instead of having to go back and readd them. Fixed issue with missing not on if blocktype is in mine. -Cleaned up the save mine function in relationship to the initial loading of mines to simplify the code and to eliminate possible problems. - - -* **New Feature: Starting to track actual block breaks in mines** -Hooked up an even monitor for BlockBreakEvents to track them within each mine. -This is a work in progress to eliminate the counting of air blocks, of which could be a strain on the server if something like holographic displays is hooked up to each mine, and runs a few times per second. -Upon server startup, had to count air blocks, but changed it to sync since on server load it was throwing too many exceptions due to entities within those chunks. -Hooked up a temp placeholder to test with, which will be removed shortly once moved in to production. - - -* **Async issue: Mine air counts** -Async failure: Well, found out the hard way there is even less that can be done with async threads. Even just checking the air counts that does not update the world can cause problems and could throw an exception. -The issue is that if a chunk has to be loaded and if there are any entities, then it will throw an exception and could possibly corrupt something. -For now i'm catching the exception and logging it. Will eliminate the async air counting in the next few days when I hook up live block counts of mined blocks. - - -* **Clear coordinates after usage** -Made changes to ensure that the coordinates are cleared after they are used. Also same for the last used mine name when that mine is deleted. - - -* **Enhancement: Better logging if major failure with rankup** -Enhanced the logging on rankup to better deal with logging even when there is major internal failures. Emphasis was to ensure transaction logging happens and is recorded no matter what. Added more details and fixed a few that were not working correctly. -Fixed a failure that was preventing rankup from happening. Had the wrong conditional testing that was preventing a rank from being assigned. - - -* **Enhancement: Placeholders optimized!** -The placeholders without the prison prefix have been eliminated since the prefix is now prefixed when it is missing prior to matching to a valid placeholder enum, and when generating PlaceholderKeys. This cuts the number of generated placeholders in half. This is significant since with the addition of the aliases there would be about 744 placeholders generated if the prison had 30 mines setup! Now a 30 mine prison would have about 372. - - -* **New Feature: Placeholder aliases!** -Added shorter versions of all placeholder commands. The aliases still must be prefixed with prison_ and if it's a mine related placeholder, then it must end with _minename. -Aliases are also displayed on the /prison version page in parenthesis following it's original placeholder name. - - -* **New Feature: Added a new placeholder! prison_rankup_cost_percent** -This indicates how close a player is to ranking up based upon their balance and expressed in percent closeness. -If their balance is zero or less, it will show zero percent. If they have more than enough money then it will show 100%. - - -* **New Feature: Added an auto rankup for all new players to the server!** -Added a rankup to the default rank on the default ladder for when a new player joins the server. -I REALLY thought this already existed!! oof!! -Modifed the rankupPlayerInternal function to supply the default ladder and default rank if needed. Also added more logging transactions to cover the new events. - - -* **Enhancement: AutoManager's BlockBreakEvent had to be set to a lower event priority** -Had to set to a EventPriorty.LOW so other plugins can work with the blocks. The other plugins were EZBlock & SellAll. This function was canceling the event after it auto picked it up, so the other plugins were not registering the blocks as being broken. The default EventPriority was originally set to NORMAL and that was not working with the other plugins. So setting it to LOW allowed them to inspect the block that was being broke, and do what they had to do, before prison's AutoManager performed the auto pickup events with it. - - -* **New Feature: Auto features added: Auto Pickup, Auto Smelt, and Auto Block!** -Gabryca added auto features to Prison. They include auto pickup, auto smelt, and auto block. - - -* **New Feature: Added detailed reporting on rankup, promote, demote, and set rank** -Added detailed logging on rankups to track all details. It may appear to be overly detailed, but if something goes wrong, it will allow tracking down exactly what may have went wrong. - - -* **New Feature: Added support for GemsEconomy and Custom Currency** -Added a direct integration for GemsEconomy so Prison can now use a custom currency with Rankups. -Added within prison the support for custom currencies. There is a special mechanism in place for dealing with custom currencies, since it requires special interfaces to specify the currency. Prison checks to make sure there is not only a registered economy that supports custom currencies, but it also checks to make sure the currency that is specified within the ranks is supported by an economy before allowing the player to add it. It also checks to make sure all custom currencies have supported economies upon Prison startup and reports errors if they are not found. When a player attempts a rankup, everything is once again checked to make sure the economies support the custom currency. Prison provides for admins to bypass the use of defined custom currencies through **/ranks promote**, **/ranks demote**, and **/ranks set rank**. - - -* **New Feature: List currencies that are used in Ranks** -On startup, gather all currencies that are defined within all of the Ranks, confirm there is a economy that supports it, and then print the list with the ranks module. If a currency is not found, then print an error message on the Prison start screen. The currencies will then be listed with each of the supporting economies when doing the /prison version command. - - -* **New Feature: Added temporal references to to the next lower and higher ranks** -To provide a much more simplified way of getting the next higher and lower ranks -when you already have a rank, I added temporal references internally to the ranks. -This means there is a zero cost associated when trying to get the next higher or lower -rank and its as simple as just another field within ranks. -These references, because they are temporal, are realigned when the ranks and ladders -are initially loaded, and whenever ladders change. - - -* **New Feature: Added base commands to /prison version listing** -Added the base commands to the /prison version, which is tied to the modules. -If a module is successfully loaded, then it will show the base commands that -it supports. - - -* **New Feature: GemsEconomy Direct integration** -Starting to hook up GemsEconomy. It's not ready and it may take a while to -put everything in place. The major thing that GemsEconomy provides is support -for non-standard currencies. - - -* **New Feature: AutoManager** -Gabryca is adding this new feature to the spigot interface. - - -* **Upgraded API: EssentialsX v2.1.7.1.0** -Update to the most recent version of EssentialsX v2.1.7.1.0 was v2.0.1-b354. -This is an internal library used only for compile purposes. - - -* **Upgraded API: SaneEconomy v0.15.0** -Update to a more recent version of SaneEconomy v0.15.0 was v0.13.1. -Note this is the last version where the signature of getBalance and setBalance is using doubles. Newer versions use BigDecimal so I've put try catches around them to capture potential errors so it can be reported. Did not upgrade to anything newer since the backend storage has changed which may be a major change for some servers. -This is an internal library used only for compile purposes. - - -* **New Feature: List all registered plugins** -To better support server owners when they have issues with Prison, the command -**/prison version** now lists all registered plugins along with their versions. -With this feature, to provide the information we need to help trouble shoot, -they only need to copy and paste to provide all the information we need. -"Please copy and paste the full **/prison version** command listing." - - -* **New Feature: prison_rankup_rank_tag added** -This provides the tag of the next available rank. - - -* **Started to Add Documentation** -To help ensure all users have access to Prison's documentation, and to be able to version all documentation, I've decided to go with github markdown documents. This will allow the documents to live within the project and they will be accessible online through github. Simple markdown hyperlinks will tie them together so the user can browse them by just clicking links to navigate. Markdown is very limited in what can be done with it, but accessibility and versioning is more important than bells and whistles. - - -* **Pulled in the Prison GUI menus** -Pulled the prison gui branch in to the bleeding branch. This was the result of the awesome work by Gabryca. -I added the mapping of /prison gui to redirect to /prisonmanager gui so it's integrated -with the standard prison commands. -Added the new permissions to the plugin.yml file. - - -* **New Feature: Mine Placeholders** -A lot of code was rewritten to support the mine related placeholders. Player placeholders -are simple since there are just a few placeholder keys. Mines are far more complex since -you have the "basic" internal placeholder keys (names), but when exposed outside of -prison, the mine names must be super imposed on each one. So if 6 mine placeholders -exist, and the server has 40 mines, then it would have to generate 240 placeholders. -Then it has to map all of those placeholders back to the internal placeholder key, so -it can identify which action to take. -Hooked the six new mine placeholders to their proper functions. -Created a mines chat handler. -Updated the player chat handler to use the new formats. Also updated MVdWPlaceholderAPI -and PlaceholderAPI to handle the new mines placeholders. - - -* **New Feature: Add in the target reset time for the mines** -This correctly sets the future targetResetTime when the next workflow job is submitted. This auto-adjusts the target time to compensate for delays in the system. -It also detects if there was a change in the reset time for the mine, and if so, then it will regenerate the jobWorkFlow to reflect those changes. - - -* **New Features: future targetResetTime, player counts within a mine, and count air blocks** -Start to hook up some mine related features such as future targetResetTime (the project time in the future when the mine will reset). This allows the creation of a count down timer until the reset happens. -Add a function to count the number of players within a mine. -Added a set of function to count the number of air blocks in a mine asynchronously. Set it up as a submittable task. The airblock count buffers and will run only every 30 seconds at most. If its a large mine, then it will delay slightly longer before refreshes to conserve computational resources. - - -* **Bug fix: Mine data was not fully loading prior to submitting workflow** -Found a timing issue where the mine's workflows were being submitted before all of -the mine related data was loaded from the file system. Over all it did not cause -too many issues, but it was defaulting back on the default values for mine resets -and was ignoring what was set for that mine. I implemented an inititialization -"channel" in the mine stacks... basically all layers of the mine's hierarchy will -kick off their constructors from the bottom (MineData) to the top (Mine). Once all -the layers are instantiated, then it kicks off executing all of the initialization -functions from the bottom (MineData) all the way back up to the top (Mine) again. -This allows the full loading of the saved mine data at the top layer, Mine, and then -allows a lower layer to utilize that loaded data, such as submitting the workflow. -This simplifies a lot of complexities pertaining to chicken-or-the-egg timings. - - -* **Compatibility Fix: Conflict with another chat plugin** -There was an onPlayerChat with the AsyncPlayerChatEvent issue -with the plugin InteractiveChat that was resulting in intermittent issues where -placeholders and on hover events were not always firing or working correctly. -Issues were resolved when the prison plugin was removed from the server that was -having this problem. -Reviewed the prison code and everything looked good, but what got things to work -correctly was setting the Spigot onPlayerChat event priority to EventPriority.LOW. - -* **New feature: /ranks set rank **. -You can now just set a rank on a given ladder, and not have to worry about multiple -promotes or demotes. -**Caution:** Use carefully, each rank that is configured must be independent of all the other -ranks. In other words, a given rank cannot expect the lower ranks to have set some -specific permission, but each rank's commands must ensure it works correctly without -hitting all the lower ranks. Same goes for when this command is used for demotions -and skipping many ranks in the process. - -* **New Features: Offline player support.** Added off line player support on some of the -commands. This now allows working with the players even if they are offline, which was not -possible before. - -* **New Features: /ranks promote and /ranks demote.** This is a way for an -admin/owner to demote or promote players directly, without incurring a cost to -the player. -This is good for testing purposes. But has a major concern. When setting up -the rank commands, the commands to remove elevated permissions must also be -included. Otherwise if a player is demoted, their perms will not be removed. - -* **Tag with v3.2.1-alpha.5 and add Core Documents shells** Started to -put together the document structures within the project. NO content yet, -but trying to hook everything up to the table of contents. More to follow! - -* **Removed Feature: Disabled the Sponge build**. The sponge project -was getting to the point that all the key functions that prison needs, has -no code and were returning nulls. Did not test the latest sponge build, -but there is no way some vital aspects would work, such as mine resets. -So commented the sponge references from gradle config files so it can be -easily reenabled if anyone wants to try to hook it back up in the future. - -* **Added command placeholders to display**. When the user is entering the -command **/ranks command add** it will now display the command placeholders -as {player} and {player_uid} so the admins/owners won't have to keep -asking what they are. They actually need to be displayed elsewhere too: TBD. - -* **Bug Fix: Glass block was not being removed** when fill mode was -enabled. Glass block will now be replaced as expected. - -* **New Feature: Mine Reset Notification Control** On a per mine -basis, notifications can now be turned off, set to a radius area from -the center of the mine, to player who are properly within the mine. -Added a command to support this new behavior: **/mines notifications**. -Each mine is independent, and there will be no global values. -As new mines are created/added they will be set to the default -radius distance which is currently 150 blocks from the center of -each mine. - -* **Bug Fix: Added PlaceholderAPI to the softdepends** Paper server -environment identified that it was missing. So I added it. Not sure -if that could have been cause issues with Multiverse loading issues? -Doubtful, but this is the first "thing" that has been found related -to hard depends or softdepends. - -* **New Feature: Command /mines resetTime** Added the command to allow -users to change the reset time for each mine. The global reset time is -only applied to new mines that are added. The new times apply once the -mines reset at the next mine reset. - -* **Work in progress: Mine resets** Committed the WIP just to get -it in git. Currently the code works, for that of which is being used. -The more complex compoennts dealing with async and paging is not yet -enabled so will have no impact yet. Also needed to commit so I can -add new features that overlap with this work (notifications). - -* **Removed dead links in README.md** A user made a reference to a few -dead links so I removed the ones that I could find. Also removed the -request for donations since that's currently a moot point. - -* **Took a quick look at tab completing" but ran in to issues with how -prison uses multi-word commands The space appears to force everything that -follows to be treated as an attribute/parameter to the root command. -Special handling of these conditions will need to be addressed later. -Tabled this attempt with hopes to return to it soon. - -* **Added new placeholder tag: prison_rank_tag** The existing placeholder -**prison_rank** returns the name of the current rank for the player. -The new placeholder **prison_rank_tag** returns that rank's tag value, -which could include formatting characters and would be suitable for -text chat prefixes. - -* **Bug Fix ?? : Cannot manually edit rank and ladder files.** -(to be addressed) -Manually editing the rank and ladder files, and maybe even the player -files, does not work, even when the server is shut down and restarted. -Could not reproduce, but a couple of users reported this as an issue and -I think I saw it once before too. Not really sure the cause but did not -see anything obvious in the code either. - -* **Bug Fix: Players on server prior to setting up prison have no ranks** -(to be addressed) -When prison is setup initially, if a player is already on the server, they -will not be assigned a player rank. This causes failures when the player -tries to use the /rankup command in that it reports "Error ! You don't have enough -money to rank up! Then next rank costs !" This happens when the rank -costs zero. - -* **Bug Fix: Found issue with the Vault Integration for Economy** -The vault economy integration was wrong. It was mixing use of player-centric and -bank-centric processing. As such balances may not have been working consistently, -and many of the vault's supported economys probably were failing to work at all. -This fix allows it work correctly and will eliminate possible failures and -intermittent issues.t - -* **Improve the reporting at startup and also for /prison version** -Added more details to provide the user with more information about -the prison environment and also the integrations. It's a work in -progress and some of the current formats will be changing and will be -refactored to be more useful and easier to read. - -* **Bug fix in third party tool: Rewrite of the SpiGet version reporting tool** -Bug fix. Third party tool. Spiget "claims" it deals with semVers when -that is nothing even close to being true. I wrote a proper version -parser to use for Prison so semVer actually works correctly which will -hopefully eliminate some situations where it fails. -I may fork the spiget project in the near future and share this -code with that project so others can benefit from proper semVer -handling, which may address some of their open issues too. - -* **Added new bStats parameter - Mines, ranks, and ladder counts** -Added a new custom parameter to bStats to record the number of mines, ranks, and -ladders that has defined at startup. So this data may now be added as custom -charts, but may not be able to ever see it online since I do not own the -bstats online account to configure it correctly on that end. But at least the -data will be there if it's even enabled. - -* **Added /ranks player command** -New command /ranks player show what rank a player currently has. The player must -be online. Future could add support for offline players, but quick attempt to -hook that results in some internal failures within the Prison plugin so deferring -on that feature. - -* **Change How Integrations Work** -All directly accessed integrations are now logged and recorded so their status can be -included with the /prison version command. Integrations that are indirectly used, -such as through other plugins like Vault, are never listed directly unless Vault -references them. - -I went though the placeholder integrations and fixed their APIs to use the newer -set of place holders. Fixed some bugs and expanded features. The list of integrations -now also includes the primary URL where they can find more information on the plugins, -and where to download them from. Also provides some additional information, such as -available place holders that can be used. - -* **Added Minecraft Version** -Added minecraft version to be stored within the plugin so it can be displayed -in /prison version and also be used -in the future with selecting block types that are appropriate for the server version -that is being ran. - -* **Bug fix: Block types not saving correctly if depending upon magic values** -Found an issue where loading blocks were by the BlockType name, but saving was by the -minecraft id, which does not always match. As a result, there was the chance a block -type would be lost, or it would revert back to the generic such as Birch Block -reverting back to Oak Block. - -* **Need to update gradle - Was at v4.10.3 - Upgraded to v5.6.4** -Currently this project is using Gradle v4.10.3 and it needs to be updated to v5.6.4 or -even v6.0.1 which is the current latest release. It was decided to only take the project -to v5.6.4 for now, and wait for the next release on v6.x, which may gain more stability? -But to do that it must be incrementally updated to each minor version and you cannot just -jump ahead or there will be failures. At each step you need to evaluate your build scripts and -then make needed adjustments before moving onward. - - * **Versions Upgraded To:**: **v5.0**, **v5.1.1**, **v5.2.1**, v5.3.1, v5.4.1, v5.5.1, **v5.6.4**, - * **Versions to be Upgraded To**: v6.0, v6.0.1 - * gradlew wrapper --gradle-version 5.0 :: Sets the new wrapper version - * gradlew --version :: Will actually install the new version - * gradlew build :: Will build project with the new version to ensure all is good. If build is good, then you can try to upgrade to the next version. - * Update to v5.0 was successful. Had to remove enableFeaturePreview('STABLE_PUBLISHING') - since it has been deprecated. It does nothing in v5.x, but will be removed in v6.0. - * Update to v5.1.1, v5.2.1, v5.3.1, v5.4.1, v5.5.1, v5.6.4 was successful. - - -* **Minor clean up to Gradle scripts** -The "compile" directive is actually very old and was deprecated back around version -v2.x. The replacements for that is "implementation" or "api" instead. The use of -api does not make sense since its use is to tag when internal functions are exposed -to the outside world as if it will be used as an externally facing API. That -really does not fit our use case, but what api also does is to force compiling all -source that is associated with something marked as api, including everyone's children. So performance will suffer due to that usage, since it shuts down incremental -building of resources. - -I also found that use of compileOnly may not be used correctly, but at this point -I'm just leaving this as a mention and then revisit in the future if time -permits, or issues appear to be related. Its a very old addition that provided -gradle with "some" maven like behaviors. It was only intended to be strictly used -for compile time dependencies, such as for annotations that are only needed for -compile-time checks, of which the plugins and resources we have marked as -compileOnly do not fit that use case. -[discuss.gradle.org: compileOnly](https://discuss.gradle.org/t/is-it-recommended-to-use-compileonly-over-implementation-if-another-module-use-implementation-already/26699/2) - - -* **Redesigned mine block generation works - Async and paged enabled** -Redesigned how prison blocks are generated to improve performance and to allow the -asynch generation of blocks, but more importantly, allows for paging of actual -block updates. The paging is a major feature change that will allow for minimal -impact on server lag, even with stupid-large mines. The idea is to chop up the -large number of blocks that need to be regenerated in to smaller chunks that can -be performed within one or two ticks, then defer the other updates to the future. -Thus freeing up the main bukkit/spigot execution thread to allow other tasks -to run to help prevent the server from lagging. - -* **Support for LuckPerms v5.0.x** -In addition to supporting older versions of LuckPerms, Prison now is able to -integrate LuckPerms v5.0.x or LuckPerms v.4.x or earlier. Take your pick. - -* **Minor changes to reduce the number of compiler warnings** -Minor changes, but better code overall. - - -* **Improved mine regeneration performance by 33.3%** -Figured out how to improve performance on mine regeneration by roughly about 33.3% overall. This -could help drastically improve performance and reduce lag since block updates must run -synchronously to prevent server corruption (limitation is due to the bukkit and spigot api). - -* **Mine stats and whereami** -Added a new command, **/mines stats**, to toggle the stats on the mine resets. Viewable with **/mines list** and **/mines info**. Stats are now within the MineManager so it can be accessed from within -the individual mines. -Added a new command, **/mines whereami**, to tell you what mine you are in, or up to three mines you are nearest to and the distance from their centers. - - -* **Major restructuring of how Mines work - Self-managing their own workflow** -They now are able to self-manage their own workflow for sending out notifications and for resetting automatically. -Mines is now layered, where each layer (abstract class of its ancestors) contributes a type of behavior and business logic that allows Mines to be more autonomous. -As a result, PrisonMines and MineManager are greatly simplified since they have less to manage. -Because Mines are now self-managing their own workflow, and they have taken on a more expanded role, some of the mine configurations are obsolete and removed. -Mines only notify players that are within a limited range of their center; they no longer blindly broadcast to all players within a given world or the whole server. -Mines extend from MineScheduler, which extend from MineReset, which extend from MineData. Each layer focuses on it's own business rules and reduces the clutter in the others, which results in tighter -code and less moving parts and less possible errors and bugs. - - -* **Concept of distance added to Bound objects** -Added the concept of distance between two Bound objects so as to support new -functionalities between mines and players. - - -* **Gradle now ready to upgrade to v5** -Resolved the last few issues that would have caused issues when upgrading to gradle -v5. Explored how gradle can use java fragments and variables. - - -## tag v3.2.0 - 2019-12-03 - - -* **Now works in 1.14.4!!** -Added in the missing library to get it to work with 1.14.4. - - -* **Fixed issue with pull request 132** -Fixes the https://github.com/PrisonTeam/Prison/pull/132 pull request. -It causes prison to fail on a clean server and throws a class not found exception. -The new library needs compile instead of compileOnly and it must also be shadowed. - - -* **Update to org.inventivetalent.spiget-update** Updated to version 1.4.2-SNAPSHOT since -the old version 1.4.0 was no longer available. - - -* **Updates to bStats** The Maven repository was updated and so was the version of -bStats that is being included on the project. It is now using the current 1.5 version, -was using 1.3 which is no longer available in the repository and was causing a build -failure for gradle. - - -* **New Feature - Decimals in Block chances now supported!** -Added support to display and use two decimal positions on block chances. - - -* **Fix - TP of Players out of the Mines upon Rest** -This is one part of a multi-step process to help ensure players are TP'd out of mines upon -a reset. In an effort to help start to address the -known bug [![Mine doesn't teleport to safety #82](https://github.com/PrisonTeam/Prison/issues/82)] -Rewrote the player teleport function to help address the issue. - - -* **New Feature - Block search!!** -You can now search for blocks to add to the mines! It uses the BlockTypes and is able -to search on the ID and the enumeration name. It displays up to 10 at a times and -provides Next Page and Previous Page controls to page through the results. -If you click on a BlockType, it will suggest the command for adding blocks: -** /mines block add %** All the user needs to do is -fill in the percent and change the "" to a valid mine name. - - -* **Create Test plans** -To better ensure all test servers are tested consistently, some basic test plans have been -created to use during online testing. They are important for consistency when testing -all of the supported versions, especially to ensure nothing is skipped. These will -evolve over time as needed. -Test server versions used in testing: - * **Minecraft 1.8.8** - * **Minecraft 1.9.4** - * **Minecraft 1.10.2** - * **Minecraft 1.11** - * **Minecraft 1.12.2** - * **Minecraft 1.13.2** - * **Minecraft 1.14.4** - - -* **Major refactoring of the prison-mines package** -Took some time to refactori parts of the prison-mines package. -Eliminated duplication of source code, and repetitive calculations. Found a few -possible bugs and reworked the code improve performance and stability. - - -* **Found another possible cause for suffocation after a mine reset** -Identified what could have been yet another cause of some of the suffocation issues -during a mine reset. It was not related so much to a bug or code, so it wouldn't -be something that could be detected with debugging. What it appears to have been -is related to the speed in which the mines reset, or more exactly, the -server lag or load. If the player is TP'd and then the mines are slow at being reset, -then the player may fall back in to the mine where they would be suffocated. -To address this issue, after the mine is fully reset, it checks to see if anyone has -fallen back in to the mine and will TP them back out to safety. - - -* **Update gson library from v1.7 to v1.8.6** -Updated library. - - -* **Removed the unused library com.fasterxml.jackson** -This library was not used anywhere so it was removed from the gradle configs. - - -* **Removed the unused library json-simple v1.1.1** -This is also an obsolete and archived project. Removed to reduce compile time -and bloat of the build. - - -* **TP Player if feet are one block below mine** -Technically they would not be standing within the mine, but since their head is within the -mine they could suffocate when the mine resets. So include the layer below the mine -to determine if the player needs to be TP'd out. - - -* **Created a unit test for player being one block below the mine** -This is to ensure the player will be properly identified as being within the mine, although -they are standing one layer below the mine. - - -* **TP Player up one block higher** -The player needs to be TP'd one block higher if a spawn does not exist. -The former vertical target needed to be one block higher. This got lost -within the prior refactoring. - - -* **Prevent adding new blocks that have a chance of zero** -The user cannot add blocks to a mine if they provide a zero chance. - - -* **Found a bug - Mines would not generate new random pattern** -Refactoring the mine generation code made obsolete a pre existing check for block -regeneration which prevented new fill patterns from being generated for the mines. -Removed the check and it resolved the issue. - - -* **New feature - Created RowComponent to group multiple FancyMessages on Same Line** -This now allows easy generation of more complex content where there can be -more than one FancyMessage (has hover text, suggests, and run capabilities when mousing) -per row. This allows putting the two buttons for block search on the same -chat row to reduce lines consumed. - - - -* **Upgraded Gradle - Was at v4.4.1 - Upgraded to v4.10.3** -This project was using Gradle v4.4.1 and should be updated to v5.6.4 or -even v6.0.1 which is the current latest release of Gradle. -But to do that it must be incrementally updated to each minor version to identify -the future changes to gradle, such as deprecated features. As features are deprecated, they -provide details on how to adjust your build scripts, but those hints are removed in future -releases. - - * **Versions Upgraded To:**: **v4.4.1**, **v4.5.1**, **v4.6**, **v4.7**, **v4.8.1**, **v4.9**, **v4.10.3**, - * **Versions to be Upgraded To**: v5.0, v5.1.1, v5.2.1, v5.3.1, v5.4.1, v5.5.1, v5.6.4, v6.0, v6.0.1 - * gradlew wrapper --gradle-version 4.5.1 :: Sets the new wrapper version - * gradlew --version :: Will actually install the new version - * gradlew build :: Will build project with the new version to ensure all is good. If build is good, then you can try to upgrade to the next version. - * Gradle v4.10.3 version of the project's build scripts has a few v5.0 issues that - need to be addressed before upgrading any farther. Future upgrades will be performed - after these issues are addressed. ETA unknown. - - -* **Removed Guava Caching** -There were a number of reasons (about 18) for the removal of Guava caching. Primarily -it really wasn't being used and the use case of the data does not warrant caching. -Removal of caching also helped to reduce memory consumption and reduce the overhead -associated with the caching library. - - -* **Update the FileStorage Class** -Provided Java docs and also the logging of warnings. -Altered the behavior so it actually does not delete a FileDatabase but instead it virtually deletes it. -This provides the user with a way to undelete something if they realize later they should not have -deleted it To undelete it, they would have to manually rename the underlying directory and then -restart the server (but the data is not lost!). -Also cleaned up the nature of some of the code so the functions have one exit point. -Updated Storage so the functions are declared as public and so createDatabase and deleteDatabase returns -a boolean value to indicate if it was successful so the code using these functions know if it should -generate warnings. - - -* **Refactored the Virtual Delete** -I created an abstract class that has the virtual delete code in it so now anything that needs to use -that functionality can extend from that class. I updated FileStorage so it now extends from -FileVirtualDelete. - - -* **Refactored FileStorage, FileCollection, and FileDatabase that were in the src/test packages** -I deleted these three source files from the prison-spigot module. Not sure why they were there, but -simple refactoring made these obsolete. - - -* **Found and fixed a fatal bug in PrisonMines.enable()** -Within PrisonMines.enable() the errorManager was being instantiated AFTER initConfig but if there was a -failure with initConfig, then it would have hit a Null Pointer Exception since that was what the value -of errorManager was, a null since it was not initialized yet. - - -* **Created FileIO, JsonFileIO, and FileIOData** -Created a couple of classes and an interface to deal better with saving and loading of the data and -to also better encapsulate the generation of the JSON files. The MinesConfig class was the first -class to get this hooked up with, which simplified a great deal of the code that deals with files. - - -* **Minor updates to PrisonMines class** -asyncGen is not being used right now, so commented it out to eliminate warnings. Performance -improvements may have made this obsolete. May revisit in the future with actual mine -resets instead of just precomputing. -Also clear the precomputed new blocks for the mines to free up memory between resets of the mines. - - -* **Major changes for the FileCollection and Document related classes** -This was a major change that encompasses the removal of Guava, the caching library. -Everything works the same as before, but with the exception of saving the individual -files as change occur; that will be added in next. This touched basically every module -including the prison-ranks. - - -* **Update FileStorage and FileDatabase** -These changes are fairly similar in nature and the two classes are so very similar. -Maybe in the future they can be merged so there is the same code base handling both of them. - - -* **Various clean up items** -Like removal of useless comments that are in the wrong places. Fixing includes that are including -packages that are not being used. Removal of warnings. Etc... just mostly items that will result -is easier to read code without any functional changes (and no program changes in most places). - - -* **Simple refactorings** -There were a few items that were refactored back in to their controlling class. For example ranks -and ladders add on an id to generate their file names. Created a filename function for those -classes so externally all users of those classes do not have to know what the business rules are -for constructing the filenames. This also can help to eliminate errors in the future; only one -location for constructing filenames instead of a few different locations. - - -* **New Feature: Add a text component to RowComponent** -Expanded the ability of RowComponent to accept parameterized text now. - - -* **New Feature: Add volume to the mines info** -Provide a little more information for mines by now showing the mine's volume. - - -* **Bug fix - Mine blocks updating wrong values and problems deleting blocks** -Fixed a few bugs with adding, setting, and deleting by the wrong value. By default -it was trying to delete by id, but multiple blocks have the same id, so it was -corrupting the block lists for a mine. -It now uses the block name instead of block id. This eliminated problems. - - -* **New Feature - Identify all BlockTypes that are blocks as blocks** -Trying to define each BlockType as a BLOCK or not. This will be used to filter -the results on /mines block search to ensure only blocks that are placeable can be -set in the mines. Tried to programatically identify what a block is within all -supported minecraft versions, but it did not work due to conflicts with the -blocks names within Materials and within the Prison plugin's BlockType enum. -Manually marked each BlockType since programatic attempts were running in to -numerous issues. There may be a few that do not -make sense or are incorrect, but can update later when found. Created a new enum -by the name of MaterialType that is used to mark the BlockTypes as -BLOCKs. Can also use that enum to label the other items with something more -meaningful such as ITEMs, or even ARMOR or WEAPON. Can have a great deal of -flexibility moving forward with that. - - -* **New Feature - Block search new only includes blocks that are actually placable in the mines** -Hooked up the BlockType.getMaterialType() == MaterialType.BLOCK to the block -search and the block add. - - -* **New Feature - Added confirm on Mine Delete** -Added a new feature to provide a confirmation when deleting a mine. The user can -click on the notification message to have the command reentered for them, then they -only need to change **cancel** to **confirm**. -This will help prevent accidental deletion of mines. Yes mines can be manually -undeleted, but this can prevent mistakes. - - -* **New Feature - Using /mines set block will add new blocks** -If you click on a block from under /mines list and you change the mine's name on that -/mines block set command, it will be treated like an add instead of an error. -This is beneficial if you want to copy a block from one mine to another and you forget -to change "set" to "add". - - -* **New Feature - Added a center Location to Bounds** -Added a center location for Bounds which will be used for a few things for mines. -Currently it was added as a fall back location for if a spawn point does not exist for -teleporting in to a mine. But it will also be used to identify all players within a -given radius from that location to selectively target broadcast messages pertaining -to that mine. - - -* **New Feature - Clone existing Locations** -Makes it easier to create clones of Locations. - - -* **New Feature - Track last Mine name used and substitute it for the generic place holder** -Track what the last value for mine was, and put it on a timer. If it was last -referenced within 30 minutes, then use that reference by default in the block -search function. -In the future, when auto suggest is enabled, this value will also be used for the -targeted mine names instead of just a generic place holder. - - -* **New Feature: TP to each mine** -Added a new feature so an admin could TP directly to each mine. If the mine's spawn location -is not set, then it will tp them to the center of the mine, but on top of the surface. -Also, if there is an air block at the player's feet, it will auto spawn in a glass block so -they would not take fall damage if there is a significant void below them. - - -* **Enhanced /mines list now includes more details** -Enhanced the /mines list to show more details about the mines, plus provide a clickable -way to TP to each mine. - - -* **Fix - Removed color codes from commands** -Color codes do not work well with 1.14.4. Removed them. - - -* **Fixed some issues with deleting a mine** -Changed the way the delete mine command works with the user messages. -Its clear as to what's going on and what the user has to do with the confirmations. -The time to confirm is limited, and reissues the start of the command if the user -misses the window to confirm. - +* **Bug fix: Fix an NPE with /sellall** +Remove of many NPE Objects and new messages for sellAll. New messages added for sellAll in the messageConfig config -#### v3.2.0 Known Issues: To be addressed +* **v3.2.3-alpha.1 2020-11-22** -* **Mine TP of Players who logout or set a home in the mines** -If a player logs out of the server when they are in the mines, or if they -set a home within the mines, there currently isn't an event handler that -will TP them to safety when they log back in, or tp to that home location. -This feature is planned for the future, but no ETA has been set. +* **Bug fix: Allows blocks to be added to mines now.** +Thought for sure I removed this code before. Not sure what happened, but must have missed testing with adding blocks. :( +Will re-release the v3.2.2 version. +# **V3.2.2 Release - 2020-11-21** diff --git a/docs/images/prison_docs_012_prison_basics_01.png b/docs/images/prison_docs_012_prison_basics_01.png new file mode 100644 index 000000000..a79e35ee8 Binary files /dev/null and b/docs/images/prison_docs_012_prison_basics_01.png differ diff --git a/docs/images/prison_docs_0xx_placeholderapi_01.png b/docs/images/prison_docs_0xx_placeholderapi_01.png new file mode 100644 index 000000000..ac12eee78 Binary files /dev/null and b/docs/images/prison_docs_0xx_placeholderapi_01.png differ diff --git a/docs/images/prison_docs_310_guide_placeholders_7.png b/docs/images/prison_docs_310_guide_placeholders_7.png new file mode 100644 index 000000000..bc679f50e Binary files /dev/null and b/docs/images/prison_docs_310_guide_placeholders_7.png differ diff --git a/docs/prison_changelog_v3.2.0.md b/docs/prison_changelog_v3.2.0.md new file mode 100644 index 000000000..eac219646 --- /dev/null +++ b/docs/prison_changelog_v3.2.0.md @@ -0,0 +1,339 @@ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +# Prison Build Logs for v3.2.0 - 2019-12-03 + +## Build logs + - **[v3.2.3-alpha - Current](../changelog_v3.2.x.md)** + - **[v3.2.0 - 2019-12-03](prison_changelog_v3.2.0.md)** + - **[v3.2.1 - 2020-09-27](prison_changelog_v3.2.1.md)** + - **[v3.2.2 - 2020-11-21](prison_changelog_v3.2.2.md)** + + +Greetings! I'm delighted that you are interested in the build logs for the +Prison plugin. I'm wanting to provide a more formal documentation as to what +is going on in each build so you have a better idea if it may be something +that you need. + + + + +# V3.2.0 - 2019-12-03 + +* **Now works in 1.14.4!!** +Added in the missing library to get it to work with 1.14.4. + + + +* **Fixed issue with pull request 132** +Fixes the https://github.com/PrisonTeam/Prison/pull/132 pull request. +It causes prison to fail on a clean server and throws a class not found exception. +The new library needs compile instead of compileOnly and it must also be shadowed. + + +* **Update to org.inventivetalent.spiget-update** Updated to version 1.4.2-SNAPSHOT since +the old version 1.4.0 was no longer available. + + +* **Updates to bStats** The Maven repository was updated and so was the version of +bStats that is being included on the project. It is now using the current 1.5 version, +was using 1.3 which is no longer available in the repository and was causing a build +failure for gradle. + + +* **New Feature - Decimals in Block chances now supported!** +Added support to display and use two decimal positions on block chances. + + +* **Fix - TP of Players out of the Mines upon Rest** +This is one part of a multi-step process to help ensure players are TP'd out of mines upon +a reset. In an effort to help start to address the +known bug [![Mine doesn't teleport to safety #82](https://github.com/PrisonTeam/Prison/issues/82)] +Rewrote the player teleport function to help address the issue. + + +* **New Feature - Block search!!** +You can now search for blocks to add to the mines! It uses the BlockTypes and is able +to search on the ID and the enumeration name. It displays up to 10 at a times and +provides Next Page and Previous Page controls to page through the results. +If you click on a BlockType, it will suggest the command for adding blocks: +** /mines block add %** All the user needs to do is +fill in the percent and change the "" to a valid mine name. + + +* **Create Test plans** +To better ensure all test servers are tested consistently, some basic test plans have been +created to use during online testing. They are important for consistency when testing +all of the supported versions, especially to ensure nothing is skipped. These will +evolve over time as needed. +Test server versions used in testing: + * **Minecraft 1.8.8** + * **Minecraft 1.9.4** + * **Minecraft 1.10.2** + * **Minecraft 1.11** + * **Minecraft 1.12.2** + * **Minecraft 1.13.2** + * **Minecraft 1.14.4** + + +* **Major refactoring of the prison-mines package** +Took some time to refactori parts of the prison-mines package. +Eliminated duplication of source code, and repetitive calculations. Found a few +possible bugs and reworked the code improve performance and stability. + + +* **Found another possible cause for suffocation after a mine reset** +Identified what could have been yet another cause of some of the suffocation issues +during a mine reset. It was not related so much to a bug or code, so it wouldn't +be something that could be detected with debugging. What it appears to have been +is related to the speed in which the mines reset, or more exactly, the +server lag or load. If the player is TP'd and then the mines are slow at being reset, +then the player may fall back in to the mine where they would be suffocated. +To address this issue, after the mine is fully reset, it checks to see if anyone has +fallen back in to the mine and will TP them back out to safety. + + +* **Update gson library from v1.7 to v1.8.6** +Updated library. + + +* **Removed the unused library com.fasterxml.jackson** +This library was not used anywhere so it was removed from the gradle configs. + + +* **Removed the unused library json-simple v1.1.1** +This is also an obsolete and archived project. Removed to reduce compile time +and bloat of the build. + + +* **TP Player if feet are one block below mine** +Technically they would not be standing within the mine, but since their head is within the +mine they could suffocate when the mine resets. So include the layer below the mine +to determine if the player needs to be TP'd out. + + +* **Created a unit test for player being one block below the mine** +This is to ensure the player will be properly identified as being within the mine, although +they are standing one layer below the mine. + + +* **TP Player up one block higher** +The player needs to be TP'd one block higher if a spawn does not exist. +The former vertical target needed to be one block higher. This got lost +within the prior refactoring. + + +* **Prevent adding new blocks that have a chance of zero** +The user cannot add blocks to a mine if they provide a zero chance. + + +* **Found a bug - Mines would not generate new random pattern** +Refactoring the mine generation code made obsolete a pre existing check for block +regeneration which prevented new fill patterns from being generated for the mines. +Removed the check and it resolved the issue. + + +* **New feature - Created RowComponent to group multiple FancyMessages on Same Line** +This now allows easy generation of more complex content where there can be +more than one FancyMessage (has hover text, suggests, and run capabilities when mousing) +per row. This allows putting the two buttons for block search on the same +chat row to reduce lines consumed. + + + +* **Upgraded Gradle - Was at v4.4.1 - Upgraded to v4.10.3** +This project was using Gradle v4.4.1 and should be updated to v5.6.4 or +even v6.0.1 which is the current latest release of Gradle. +But to do that it must be incrementally updated to each minor version to identify +the future changes to gradle, such as deprecated features. As features are deprecated, they +provide details on how to adjust your build scripts, but those hints are removed in future +releases. + + * **Versions Upgraded To:**: **v4.4.1**, **v4.5.1**, **v4.6**, **v4.7**, **v4.8.1**, **v4.9**, **v4.10.3**, + * **Versions to be Upgraded To**: v5.0, v5.1.1, v5.2.1, v5.3.1, v5.4.1, v5.5.1, v5.6.4, v6.0, v6.0.1 + * gradlew wrapper --gradle-version 4.5.1 :: Sets the new wrapper version + * gradlew --version :: Will actually install the new version + * gradlew build :: Will build project with the new version to ensure all is good. If build is good, then you can try to upgrade to the next version. + * Gradle v4.10.3 version of the project's build scripts has a few v5.0 issues that + need to be addressed before upgrading any farther. Future upgrades will be performed + after these issues are addressed. ETA unknown. + + +* **Removed Guava Caching** +There were a number of reasons (about 18) for the removal of Guava caching. Primarily +it really wasn't being used and the use case of the data does not warrant caching. +Removal of caching also helped to reduce memory consumption and reduce the overhead +associated with the caching library. + + +* **Update the FileStorage Class** +Provided Java docs and also the logging of warnings. +Altered the behavior so it actually does not delete a FileDatabase but instead it virtually deletes it. +This provides the user with a way to undelete something if they realize later they should not have +deleted it To undelete it, they would have to manually rename the underlying directory and then +restart the server (but the data is not lost!). +Also cleaned up the nature of some of the code so the functions have one exit point. +Updated Storage so the functions are declared as public and so createDatabase and deleteDatabase returns +a boolean value to indicate if it was successful so the code using these functions know if it should +generate warnings. + + +* **Refactored the Virtual Delete** +I created an abstract class that has the virtual delete code in it so now anything that needs to use +that functionality can extend from that class. I updated FileStorage so it now extends from +FileVirtualDelete. + + +* **Refactored FileStorage, FileCollection, and FileDatabase that were in the src/test packages** +I deleted these three source files from the prison-spigot module. Not sure why they were there, but +simple refactoring made these obsolete. + + +* **Found and fixed a fatal bug in PrisonMines.enable()** +Within PrisonMines.enable() the errorManager was being instantiated AFTER initConfig but if there was a +failure with initConfig, then it would have hit a Null Pointer Exception since that was what the value +of errorManager was, a null since it was not initialized yet. + + +* **Created FileIO, JsonFileIO, and FileIOData** +Created a couple of classes and an interface to deal better with saving and loading of the data and +to also better encapsulate the generation of the JSON files. The MinesConfig class was the first +class to get this hooked up with, which simplified a great deal of the code that deals with files. + + +* **Minor updates to PrisonMines class** +asyncGen is not being used right now, so commented it out to eliminate warnings. Performance +improvements may have made this obsolete. May revisit in the future with actual mine +resets instead of just precomputing. +Also clear the precomputed new blocks for the mines to free up memory between resets of the mines. + + +* **Major changes for the FileCollection and Document related classes** +This was a major change that encompasses the removal of Guava, the caching library. +Everything works the same as before, but with the exception of saving the individual +files as change occur; that will be added in next. This touched basically every module +including the prison-ranks. + + +* **Update FileStorage and FileDatabase** +These changes are fairly similar in nature and the two classes are so very similar. +Maybe in the future they can be merged so there is the same code base handling both of them. + + +* **Various clean up items** +Like removal of useless comments that are in the wrong places. Fixing includes that are including +packages that are not being used. Removal of warnings. Etc... just mostly items that will result +is easier to read code without any functional changes (and no program changes in most places). + + +* **Simple refactorings** +There were a few items that were refactored back in to their controlling class. For example ranks +and ladders add on an id to generate their file names. Created a filename function for those +classes so externally all users of those classes do not have to know what the business rules are +for constructing the filenames. This also can help to eliminate errors in the future; only one +location for constructing filenames instead of a few different locations. + + +* **New Feature: Add a text component to RowComponent** +Expanded the ability of RowComponent to accept parameterized text now. + + +* **New Feature: Add volume to the mines info** +Provide a little more information for mines by now showing the mine's volume. + + +* **Bug fix - Mine blocks updating wrong values and problems deleting blocks** +Fixed a few bugs with adding, setting, and deleting by the wrong value. By default +it was trying to delete by id, but multiple blocks have the same id, so it was +corrupting the block lists for a mine. +It now uses the block name instead of block id. This eliminated problems. + + +* **New Feature - Identify all BlockTypes that are blocks as blocks** +Trying to define each BlockType as a BLOCK or not. This will be used to filter +the results on /mines block search to ensure only blocks that are placeable can be +set in the mines. Tried to programatically identify what a block is within all +supported minecraft versions, but it did not work due to conflicts with the +blocks names within Materials and within the Prison plugin's BlockType enum. +Manually marked each BlockType since programatic attempts were running in to +numerous issues. There may be a few that do not +make sense or are incorrect, but can update later when found. Created a new enum +by the name of MaterialType that is used to mark the BlockTypes as +BLOCKs. Can also use that enum to label the other items with something more +meaningful such as ITEMs, or even ARMOR or WEAPON. Can have a great deal of +flexibility moving forward with that. + + +* **New Feature - Block search new only includes blocks that are actually placable in the mines** +Hooked up the BlockType.getMaterialType() == MaterialType.BLOCK to the block +search and the block add. + + +* **New Feature - Added confirm on Mine Delete** +Added a new feature to provide a confirmation when deleting a mine. The user can +click on the notification message to have the command reentered for them, then they +only need to change **cancel** to **confirm**. +This will help prevent accidental deletion of mines. Yes mines can be manually +undeleted, but this can prevent mistakes. + + +* **New Feature - Using /mines set block will add new blocks** +If you click on a block from under /mines list and you change the mine's name on that +/mines block set command, it will be treated like an add instead of an error. +This is beneficial if you want to copy a block from one mine to another and you forget +to change "set" to "add". + + +* **New Feature - Added a center Location to Bounds** +Added a center location for Bounds which will be used for a few things for mines. +Currently it was added as a fall back location for if a spawn point does not exist for +teleporting in to a mine. But it will also be used to identify all players within a +given radius from that location to selectively target broadcast messages pertaining +to that mine. + + +* **New Feature - Clone existing Locations** +Makes it easier to create clones of Locations. + + +* **New Feature - Track last Mine name used and substitute it for the generic place holder** +Track what the last value for mine was, and put it on a timer. If it was last +referenced within 30 minutes, then use that reference by default in the block +search function. +In the future, when auto suggest is enabled, this value will also be used for the +targeted mine names instead of just a generic place holder. + + +* **New Feature: TP to each mine** +Added a new feature so an admin could TP directly to each mine. If the mine's spawn location +is not set, then it will tp them to the center of the mine, but on top of the surface. +Also, if there is an air block at the player's feet, it will auto spawn in a glass block so +they would not take fall damage if there is a significant void below them. + + +* **Enhanced /mines list now includes more details** +Enhanced the /mines list to show more details about the mines, plus provide a clickable +way to TP to each mine. + + +* **Fix - Removed color codes from commands** +Color codes do not work well with 1.14.4. Removed them. + + +* **Fixed some issues with deleting a mine** +Changed the way the delete mine command works with the user messages. +Its clear as to what's going on and what the user has to do with the confirmations. +The time to confirm is limited, and reissues the start of the command if the user +misses the window to confirm. + + + +# v3.2.0 Known Issues: To be addressed + +* **Mine TP of Players who logout or set a home in the mines** +If a player logs out of the server when they are in the mines, or if they +set a home within the mines, there currently isn't an event handler that +will TP them to safety when they log back in, or tp to that home location. +This feature is planned for the future, but no ETA has been set. + + + diff --git a/docs/prison_changelog_v3.2.1.md b/docs/prison_changelog_v3.2.1.md new file mode 100644 index 000000000..1c281d6a2 --- /dev/null +++ b/docs/prison_changelog_v3.2.1.md @@ -0,0 +1,1005 @@ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +# Prison Build Logs for v3.2.1 - 2020-09-27 + +## Build logs + - **[v3.2.3-alpha - Current](../changelog_v3.2.x.md)** + - **[v3.2.0 - 2019-12-03](prison_changelog_v3.2.0.md)** + - **[v3.2.1 - 2020-09-27](prison_changelog_v3.2.1.md)** + - **[v3.2.2 - 2020-11-21](prison_changelog_v3.2.2.md)** + + +Greetings! I'm delighted that you are interested in the build logs for the +Prison plugin. I'm wanting to provide a more formal documentation as to what +is going on in each build so you have a better idea if it may be something +that you need. + + + + +# V3.2.1 - 2020-09-27 + +* **New Release!! v3.2.1 published!!** +Bleeding was pulled in to master branch. And published to spigotmc.org too. :) + + + +## tag v3.2.1-alpha.20 - 2020-09-27 + + + +* **Fixed issue with sorting of the mine name in the gui.** + They are now strictly by alphabetical on the mine name. + + + +* **New Feature: Custom sorting of mines, ladders, and ranks.** +Currently mines and ranks are alphabetical in sort order. +Ladders sorts default first, prestige last, and everything else is alphabetical between them. +The PrisonSortableLaddersRanks will first sort ranks by ladders, then within each ladder, they will preserve the ladder rank order, then all ranks that have no associated ladders will be sorted alphabetically and added to the last of the list. +This new feature has not been hooked up yet to any interfaces, but it's ready. +Need to add mines, but right now there is no way to link mines to ranks. + + + +* **Bug Fix: Prevent mines from being created that have spaces or no names** +A bug was found where the admin was able to create a mine with the name of two spaces. Changed create mine function to disallow any spaces within the name, or an empty name. Also setup the parms to "require" a name, but not sure if that will work correctly. If it does, then there will be multiple layers of protection to prevent spaces. + + + +* **New Feature: GUI Works with Spigot 1.8 now!** +Prison's GUI now works with spigot 1.8. + + +* **New Feature: The command /prison now includes all other root commands!** +When the command prison is used, it shows a list of all sub-commands. Now it also includes all other Prison registered root commands so the uses do not have to guess what other commands are available within prison. This will provide a listing so they can explore others. +Also disabled the prison troubleshoot command since its not of any benefit. + + +* **Moved the spiget project in to the prison project's class path** +Move the spiget in to the project's directory with shadowJar since there has been a few issues with the build. + + +* **New Feature: /mines tp Can Now teleport players within a rank command** +Allow only admins or console commands or rank commands to teleport someone by name. +This allows rank commands to use this to teleport a player when they rank up. + + + +* **Alpha 20 - 2020-09-16** +Yeah. I know. Alpha 20 and not beta! +But many releases have happened under Alpha 19 including some bug fixes. This is incrementing to help ensure when someone grabs the most recent, they know if they have the most recent. +Beta will follow shortly, but there are still a few more additions and adjustments. + + +* **Tweaks to auto manager** +Found duplication on durability processing. Eliminated the duplication, but now it will only be applied when auto pickup is enabled. Not 100% sure if that is the best logic, but figuring if prison does not handle the block break event, then do not apply the durability. +May have to revisit and tweak how smelt and blocking is working too. +Changed the ALL pickup to be the first processed since that is probably going to be the most common situation so bypass the many block checks to save some CPU time. + + +* **Attempts to force the plugin's config.yml file to be reloaded** +It "should" work, but it does not. +Keeping this code since I will expand upon it and get it working, even if I have to go outside the bukkit handling of that file. + + +* **Bug fix: Duplication of mine blocks. Only impacts more recent Alpha.19 releases.** +Duplicate blocks are now "fixed" when loading a mine. If a duplication fix is applied, the fixed mine data will be saved and a message will be shown that an inconsistency was detected and fixed. +Overall this did not cause any crashes or corruptions of mines, but it did duplicate internal data for the blocks associated with a given mine. +Symptoms were loss of air blocks (if you had an air percentage) or if enough blocks were duplicated, the GUI would give you an error message indicating there were too many blocks and it could not display them all. +The issue was initially thought to be related to a lambda function, but that was rewritten and confirmed that it wasn't there. The issue was ultimately tracked back to a typo on the new block handling. So this would have only impacted the more recent alpha.19 releases (not all). + + +* **New Feature!! A Reset Threshold Percentage has been added.** +Before the reset threshold was set to zero blocks. Now, if enabled, it will reset the mine at another predetermined percentage of blocks remaining. +A value of zero disables this feature since that is the same as a zero block reset. + + +* **Changed mines placeholder for time remaining formatted** +Dropped the decimals since it does not look good when updating every second or less. + + +* **New Features! PLAYERMINES placeholders!! Added 24 new placeholders including aliases!!** +These placeholders are a hybrid between player and mine placeholders. These placeholders can only return results when a player is actually within a mine, and these are the mine's stats. In other words, whichever a mine a player is in, it can show all of that mine's stats. +This will not work in holographic displays since they are not associated with any players. It will work with chat prefixes, but these are stats you generally don't want as chat prefixes (maybe just the mine's name?). +But where these really can be awesome is used in the player's scoreboard. So when they hop in a mine, they can pull up in their scoreboard stats on the mine itself. + + +* **Bug fix: Placeholder progress bar configs in config.yml not working** +This addresses some issues with being able to load the placeholder progress bar configs from the config.yml file. +Ran in to issues with symbols not being quoted. Strings normally do not have to be quoted, but yaml was interpreting them incorrectly and was trying to treat them as special values. So quoting prevents that. +Also had unicode characters in the comments which also may have be causing issues indirectly, so removed them. + + +* **New Feature! Placeholder progress bars!** +prison_rankup_cost_bar, prison_rankup_cost_bar_laddername, prison_mines_timeleft_bar_minename, prison_mines_remaining_bar_minename, plus their aliases. +This adds a configurable progress bar to the list of placeholders. The /plugins/Prison/config.yml file can be reset to load the parameters to customize the progress bars. For now, if the configs do not exist, they will fall back on to the default values. + + +* **Minor fix: Found that some placeholder key values were not being generate with all lower case characters.** +This could have resulted in problems if the users were trying to use all lower case. +Also provided a placeholder flags exclusion filter to remove the wrong compound types within mines. + + +* **Minor improvement to placeholder search when using Players** +Added player information when it's supplied with the placeholder search. This provides important feedback to the user that the supplied player is valid. + + +* **Bug fix: For the PlayerManager was not allowing PlaceHolderFlags types of LADDERS to be processed.** +So ladder based placeholders were not being translated correctly (sometimes they were). This was fixed. + + +* **Eliminate the obsolete message and .meta checks.** +This version of prison cannot perform any updates on the old obsolete versions of data. That functionality was removed prior to the v3.1.1 release. To upgrade from v2.x they will first have to upgrade to v3.0.0 and then to the current release. + + + +* **Move the player mine cache to the PrisonMines object** +This will allow it to be accessible from other areas within the prison plugin. This will need to be used with more advanced placeholders that will be added shortly. + + +* **Enhancement: Optimize the generation of placeholders** +OPtimizing placeholders by eliminating the generated placeholder that lacks the prison_ prefix. Instead, adding the prison_ prefix to all identifiers that are lacking it so it can get a hit on the real entry. Fix the display of the stats... was calling wrong function. + + +* **New Features! Added 4 new placeholders - Cost Remaining** +These pertain to cost remaining for rankup. +prison_rankup_cost_remaining, prison_rcr, prison_rankup_cost_remaining_laddername, prison_rcr_laddername +Now you can count down the amount of money needed for players to rank up! Remaining value is never negative, but it shows zero instead. + + +* **Few Feature! Reload Placeholders** +Provided a reset function for placeholders. The new command is registered twice to provide the most flexibility. +**/prison placeholders reload** and **/prison reload placeholders** + + +* **Realigning source for Spigot Placeholder code.** +Moved a ton of placeholder code to the tech.mcprison.prison.spigot package to get it out of the SpigotPlatform class. +There was way too much business knowledge being exposed within SpigotPlatform and wanted to group it all under a placeholder's package. +The real meat of placeholders has to come together within spigot because core has no knowledge or access to the mines module, or the rank module. +This required creating a new interface and pulling the majority of the functions out of the Platform interface. + + +* **Change in SpigotListener to use the singleton that already exists** +Changed to use the singleton instead of the passed object. Cleaner. + + +* **Bug Fix: Fixed a mine's block type loading issue.** +The blocks are now checked against a greater range of possible values to improve match rates when reloading mines. +If a block cannot be mapped, then an error message is now printed to the console so it can be addressed. +There was an issue with QUARTZ_PILLAR not being able to be mapped back to the correct block type. + + +* **New Feature: Add the internal placeholder counts on startup.** +These counts are the total generated placeholders and some placeholders have more than one key. + + +* **New Feature: Added reset notification permissions** +Now only players with the mine's permission can be notified if the feature is enabled. +This setting is on a per mine basis, and the permission used is displayed in the /mines info listing. + + +* **Admins and console are able to view player's past names with /ranks player** +When admins and console use `/ranks player` command it will show past names for all players that have more than one name recorded. + + +* **This implements the tracking of the player's name** +This now tracks and detects when player names are changed so it can record the change. +This is passive in that it does not try to actively detect name changes unless the player is active within the prison and using features that require the use of the player ranks and associated details. +Offline players will never have their names updated if they are changed and they never return to prison. It is possible that a player could change their names a few times and if they do not log in to prison, then it will not be able to track all the interim name changes, only the current name they just logged in with. + + +* **Setup the internals for tracking the blocks mined for each player** +Established the core internals on tracking blocks mined per player. Nothing uses this yet. + + +* **Add support for recording player names within the RankPlayer.** +This will help admins manage their data especially if they have to work with the raw data. +Multiple names can be tracked, with the last name in the list being the current name. Players can change their name numerous times and always go back to the same name multiple times and this will record them. +This only establishes support for names, but this commit does not get the actual names. This update is able to save and read the data from the saved file. + + +* **Enhanced the /ranks info details** +Changed around the /ranks info to show the actual rank name and tag so it's obvious. Also moved the player count outside of the admin block so all players can see it. + + +* **Added GUI Compatibility interfaces and support classes** +Restructure the compatibility classes to separate the blocks from non-blocks and added in GUI support. +It maybe a little odd how the interfaces extend from other interfaces, but the chaining allows separation of functionalities to keep the code cleaner at the interface and implementation layers. + + +* **Alpha.19 - 2020-09-08** +Final alpha version prior to beta! Yeah I know I said that before, but I did not expect so much awesome stuff to be added! Need to have a clean transition to beta, so this has to happen first. + + +* **New Features: Show all ranks and player counts upon startup and on demand** +For each ladder, all ranks with the number of players at each rank is now displayed at startup of the plugin. +Also a new command was created to be able to display this information at any time. The command has the option to change the parameters to fine tune the results. The command is /ranks players. +When the rank of a player is viewed, it is now displayed to the log. An admin reported that all ranks were changed on their server, but no transactions appeared in the logs. It was shown in the logs when players checked their ranks, but it is unknown what thoes ranks were. SO this tries to record that. + + +* **New Feature: Language files are written to the prison's plugin directory by defaul** +If the language files do not exist at startup, then they will be written to the proper lang directories. This helps admins find the files and edit them without having to try to pull them from the jar file. +The core module, which is not a true Prison module is now correctly being remapped to the /plugins/Prison/module_conf/core/ directory for all language file uses. This keeps things consistent and clean. +The normal use case is that the jar file language files will be loaded first, then the external files will be loaded and replace any key value pairs that may have been loaded previously. +Warning... the language files ignore the package names and goes strictly by the key value in the files. Therefore if the same key exists in more than one language file, then the last one loaded will replace any other previously loaded values. +This has been tested and it works great. No new mapping have been added. + + +* **Added a unique permission for /rankupmax so it can be disabled.** +Its `ranks.rankupmax.[ladderName]` but the player must also have `ranks.user`. + + +* **Added more details to Ladder save files** +Added Rank names to the ladder's save file. This will help figure out what is what and could help eliminate possible errors. If a ladder is loaded and a name is added, then it will flag the ladder file to be resaved after being fully loaded to ensure the contents of the file is up to date. +No one should ever make manual changes to these files, but this at least give more information due to the use of the magic numbers with the rankIds. +Added a link to the actual Rank object to simplify the use of the objects. + + +* **New Feature: Broadcast Rankups and Demotions** +There is a now a new feature that will broadcast to the whole server when someone gets a Rankup Or a Demotion. +This can be disabled within the config.yml file. If the entry is not there, it is the same as if it has a true value. Any other value is considered false. + + +* **Alpha.18 - 2020-09-01** +Final alpha version prior to beta! + + +* **New Feature: Mine Reset Paging** +Finished hooking up the paged mine reset code. And it works too! Tweaked some of the timing settings such as milliseconds and block thresholds which will better tune this to be more responsive to paging. +Had to add comparable to the MineTargetBlockKey for the map to work correctly. +To enable use `/mines set resetpaging help`. + + +* **Bug fix: Correctly using magic values with XMaterials** +This fixes the usage of the magic value with bukkit/spigot versions prior to 1.13. The issue was that the only way to set the data value was through the BlockState and I did not force the update. Now the block type and rawData are being set only within the BlockState and then the update is forced. This resolves the issue and should work for all block types that rely on using the magic values. +The way the mapping to the XMaterial was changed to try use the name matching first since they have a high correlation. Also the the legacy matching is the last resort now. + + +* **Added v1.16.1 now officially supported and added to the test environments** +Working fine. No issues found. Now have a working v1.16.1 environment to test from to ensure issues are addressed. + + +* **Reporting for supported block types** +Added a raw spigot/bukkit test to round out the test to see how many blocks are available to prison. +Running this test on any version should give a fairly accurate idea of how many more blocks are gained with the newer versions of spigot. +Pre 1.13 versions of spigot cannot be fully tested to identify all possible block types due to lack of ensuring individual Material types with different data values within the ItemStack cannot be identified as being invalid since that is left for the client software to decide. +This test adds no new functionality, but provides a reporting on how the newer infrastructure will work. + + +* **More work on new block type support** +Got a lot of the questionable code working better so 1.8.x and 1.16.x will not have problems with class or method not found exceptions. Pushed a lot of version specifics to the compatibility classes. +This does not add new blocks to prison, but lays the foundation and support for new block types. + + +* **Major New Feature: Work In Progress! New handling of Blocks and Materials!!** +Starting major changes to how the block types and materials are processed. +This is a Work In Progress! Use with caution until stabilized. +Upgrade the spigot API to 1.13.2!!! +This should make Prison more 1.13+ compatible and support more block types, and transition to supporting all block types that exist for a given version. +Add in the cryptomorin's XSeries to better deal with newer block types. Trying to get rid of deprecated function usage, except for within spigot 1.8 specific code sets. +Finally got lapis lazuli working! So this is heading in the right direction. + + +* **Alpha.17 - 2020-07-28** + + +* **New Feature: Sellall has been added** + + +* **Worked on enhancements for the auto features.** +Enhancements and hooking up fortune, silk (does nothing... yet), durability, and additonal drops. +Enhancements to improve stability and quality +Eliminate the switch statements when dealing with Materials since there are a few that cannot be hard coded and instead must use the Material.matchMaterial() function since the type may not exist in all versions. It's also preparing to transition to another way of dealing with materials, but cannot use them until after prison is migrated to 1.13.x. + + +* **Fixing some block types so they are not hard coded.** +Initial setup. This will help transition to 1.13.x which will better position to supporting 1.15.x and 1.16.x block types. +Not all issues have been addressed yet, like the GUI. Want to confirm this is working before expanding. + + +* **Prevent the default ladders from being deleted** +The default ladder was actually deleted by a user. Could prevent a ton of issues by preventing these from being removed in error. + + +* **Enhanced the handling of unloaded modules.** +They were not behaving correctly and causing issues. Also better log the warnings that the module was not loaded. + + +* **Add documentation for Mine Commands** +Added documents for mine commands. Document how to setup a Parent Mine with Child Mines. + + +* **New Enhancement: Mine Commands Enabled and Enhanced!** +Mine commands have been enabled. They have been enhanced by adding the ability to have some commands ran before the reset, or after the reset. This gives a great control over customization and integrating external commands to operate most efficiently with actual block resets. One example is to have a real forest of trees reset and completely rebuilt each time. The other example of usage is to setup up a parent mine to control the resetting of all child mines. + + +* **Alpha.16 - 2020-07-04** + + +* **More Enhancements to AutoManager** +Some refactoring and some enhancements to AutoManager. +Added isCalculateDurabilityEnabled, isCalculateFortuneEnabled, isCalculateSilkEnabled, and lore durability resistance. +Feature enhancement: Permissions added to config file so they can be customized as needed. Added these custom permissions to the /prison automanager command so they always reflect the correct permissions. If changed online, everything reflects the changes right away. The AutoFeatures now are able to record their parents so it makes possible the ability to get all permissions related to a given section. For example all permissions, or all autoPickup permissions. + + +* **Enhance Auto Manager Features** +Still a work in progress, but becoming more mature. +**Added new feature**: Durability able to be turned on/off. +**Added new feature**: Durability resistance is now able to be used as a lore. With no integer value it will have 100% effect and disable durability calculations on the item that has the lore. If less than 100, then it's a percent chance durability will be skipped. +**To do:** Hook up a new block drop calculation and use the new fortune and silk functions. +Removed some hard coded Material types to make it more compatible with newer releases of spigot. +Reworked how lapis lazuli auto block is processed to work with v1.13.x and higher. + + +* **Upgrade the Spigot API to v1.12.2 from v1.9.4** +Prison was built on spigot api v1.9.4 for the longest time. Looking in to trying better support newer block types, had to upgrade the version to something newer. Tried v1.13.2 but it failed to compile. V1.12.2 works well. + + +* **Fixes to AutoManager and new file IO** +Got the new file IO working better since there were a few issues with getting the actual values from the spigot yaml reader. Also made changes to the ValueNode objects to make them easier to use and to be consistent between them all. + + +* **Bug Fix. NEATHER_QUARTZ is not a block** +But its type was set to a MaterialType of BLOCK. It is actually the result of breaking NEATHER_QUARTZ_ORE, of which, that is the proper block type to use. Use of neather_quartz would result in many exceptions in the console, one for each attempt. + + +* **New feature: Moved AutoManager to prison core and out of spigot module.** +This will allow access to these settings in all other modules instead of just the spigot module. +Rewrote the interface on how the the properties are saved and loaded to elimiante the dependancies upon spigot. + + +* **New Feature: Ladder specific placeholders for player ranks** +Add in placeholders for ladders. These are rank placeholders, but targeted for specific ladders. +Enhanced the `/prison placeholders search` to work with player based placeholders, and added support to specify the actual player too so it can work from the console. The placeholder search should now work with all placeholders and will be able to provide values for players if ran in game, or if the player's name is provided within the console. + + +* **Ranks names cannot contain formating** +Made it so new rank names cannot contain & formatting. It causes issues and that's what tags are for. +This change mitigates any preexisting ranks that may have been created with formatting, the /ranks list now escapes the & characters by replacing them with -. Then the /ranks info command is now able to use those escaped names. The results of this change is that new ranks cannot contain & formatting, but preexisting ranks should continue to work and could eliminate issues. +There was an issue with /ranks list and formatted names causing issues with on click events. + + +* **New Feature: Prestige! Significant work on Prestige added!** +Gabryca provided a lot of enhancements and features to the new Prestige system that he has been working on. It was merged with bleeding from it's own branch. It was pulled in because it has reached a point where it can start being used and undergo testing. + + +* **New features: AutoManager perms and lore enabled.** +Players can now use auto pickup, auto smelt, and auto block can be used if they either have the perms (all or nothing) or if the tools have the lore (0 to 100.00 percent chance). +The tool lore supports full enablement (no number following the lore) or a percent chance than can range from 0.001 through 100.000. Allows for tools to gain better chance. +The config setting Options.General.AreEnabledFeatures enables all mines and overrides player perms and lore. Set to false to allow perms and lore to work. +May need more testing, but looks functional so far. +Added new command /prison automanager to just display info on automanager and the perms that will enable it. The command only shows the help. + + +* **PlaceholderAPI Troubleshooting and Tips** +Update PlaceholderAPI install docs to reflect a possible way to get it to work with other plugins when the other third-party placeholders are not working. +At this time, it does not appear like this applies to Prison, but it coud be a tip that could be a solution for an edge case issue that someone may experince in the future. + + +* **Performance improvement in auto manager.** +This change to the auto manager has a significant performance improvement per block break by not having to reload all of the parameters each and every time a block breaks (it no longer loads from the file on each block break event which really reduced the overhead too). +This also sets up the auto manager for the next phase of enhancements. + + +* **New feature: The /mines tp now can be used by players** +If a player has the new permission: mines.tp.[mineName] they can use this command to tp to the mine. +The mine name must be all lower case. + + +* **New Feature: altPermissions on commands!** +Now if there is a permission that is internally checked within a command, it can be reported with the altPermissions so it can displayed if the user does the help keyword. +Examples: /rankup, /mines tp, and /ranks + +AltPermissions are alternative permissions that are not checked internally, or automatically. +It is up to the programmer to put hooks in to the code to check on these altPermissions. +This field of altPermissions is strictly for displaying helpful information to the end users +and it is only helpful if it is included. + +For example the command /rankup has an optional parameter ladderName. If a ladderName is +provided, then it checks to see if the player has the permission: ranks.rankup.[ladderName]. + +Because these permissions are not ever used to check for actual permissions, it is very +important to provide parameters such as [ladderName] to signify where the server owner, or +admin, must place the real ladder name within the permission. + +This is such a critically helpful feature because otherwise the only way you would know +that you need this permission is to look at the source code, of which many cannot do, and +those who can, may not know where to look. So this provides very important information that +was not available before. + + +* **New Feature: Command help keyword now includes permissions** +New Feature: Now includes the permissions in the help commands so users do not have to guess or hunt down what permissions are needed for these commands. + + +* **Fixes ladder commands: delrank and addrank** +Fixes the problem with removal and readding ranks from a ladder. +You can use /ranks ladder delrank to disconnect a rank from the ladder. Then use /ranks ladder addrank to put it back in to the ladder in a new position. + +These changes makes sure that the rankPrior and rankNext are set to null to remove dead or changed connections. It also sorts each ladder before hooking up the those links. + + +* **New Feature: Placeholder tools.** +You can now test all placeholders, including multiple placeholders within one test. +Also you can fully search for any placeholder, either player based or mine based placeholder. If you run the commands from console, you cannot use the player placeholders. +The commands: /prison placeholders test and /prison placeholders list. + + +* **Start the ground work for supporting another integration** +Initial setup for WorldGuard. Ran in to issues with lack of v6.x even existing in maven, which is needed for minecraft 1.8 through 1.12.2. WorldGuard v7.x is for minecraft versions 1.13.0 through 1.15.2. +Also both WG versions appear to use the same package and class names too, so how to include both in the build without conflict? Yeah, not sure. Will have to figure that out too. +Anyway, starting to provide the basic integrations hooks, which are disabled right now, but will be enabled as the details are worked out, and as Prison is adjusted to work better with it. + + +* **Failed Attempt to Enable 1.13 Flattened Materials** +Failed attempt to give 1.15.x the ability to have native block types. This code has been commented out with hopes that it could be used in the future. +The reason why this won't work, is not that the codes entered are incorrect, but it appears like the Material object that is actually being used when running on a Spigot 1.15.2 server is actually using code from Spigot 1.9.2 since none of the 1.13 materials are recognized at runtime. +So the "wrong" classes could be included in the build artifact, which in turns get's used during runtime. But should it? +So for now, its all disabled so it can be revisted later. + + +* **New Feature: Mine commands.** +Added commands to mines. This may be complete, but not fully tested, so disabling so it cannot be used. Will enable when it is proven to work well. +The concept with mine commands, is that after every reset, it will run a set of commands associated with the mine, of which could permit new and complex types of mines. + + +* **New Feature: IGNORE BlockType added.** +Created a new block type that will allow ignoring what is already there. +Ignore can be used instead of air, and as such it will not replace whatever is there. +It is possible that all blocks are 100% ignore so that way nothing in the mine changes during a reset. + + +* **New feature! Two new placeholders: formatted time.** +The placeholders for reset interval and time left now have formatted versions and aliases. +The format is 13d 21h 13m 1.23s. 1h 0m 13.13s. +It does not show leading digits if they are zero, such as days will be suppressed if zero. And days, hours, and minutes will all be suppressed if they are all zero. But if hour is non + + +* **Bug fix: Failure in logging upon plugin startup** +There was a failure on getting and calculating a paper 1.10.0 version due to a period to the left of the primary version. As such, the old code could not deal with it and was throwing a failure. To add to that failure, since it was during start up of the plugin, the resources were not yet setup for to allow the logging to work so that was causing another failure. +This fix allows the output of the log message to System.err so it will be at least recorded in the log files. + + +* **New Feature: Now Supports delayed world loading! Multiverse-core now properly supported!** +New Feature: Major modifications to support delayed world loading. This supports Multiverse-core, and other plugins, that may load worlds. +You cannot use softdepends or hard depends to ensure the world is loaded, but instead must use WorldLoadEvent events. +These changes enables the mines to load even when their world has not been loaded yet. It also disables any function or changes that could corrupt the mine's data by not having the world enabled and loaded. + + +* **Bug fix: Reset Radius Notification not working** +The message notification functions were not using the mine's radius value, so all radius notifications were based upon a distance of 150 blocks. +Extend within notifications to include players standing on top of the mines too. + + +* **New Feature: Start to properly deal with delayed world loading** +Plugins such as Multiverse-core may load most of their worlds after Prison has tried to load the mines. During the creation of the mines, the worlds must exist, otherwise the mines cannot be loaded under the older way prison was doing things. + +This change allows mines to be loaded, but will delay their hook up to the +world until the worlds are formally done loading. + +This is a work in progress and is not complete yet. + + +* **New Feature: New command /rankupMax will rank up the player until they are unable to afford the next rank.** + + +* **New feature: Provided a way to disable the resetting of the mine when reaching zero blocks.** + + +* **New feature: Can now disable the reset when a mine reaches zero blocks" +Provided a way to disable the resetting of the mine when reaching zero blocks. + + +* **Updates to AutoManager: Full Inventory** +Improve the full inventory handling. Basically always try to work with inventory items (auto pickup, auto smelt, and auto block) and if they cannot fit back in to inventory then just drop them. That allows them to fill up inventory slots that may not be full. +Have the dropExtra function use either the specified holographs or the action bar to show the inventory is full message. + + +* **Few fixes to mine commands, rank loading** +Fixed an issue with Mines commands. The one was a typo (had to be a stray space) and the other was using block search before using any other mine command (missed testing that before). Tweak formatting on mines info to make it easier to read. + + Fixed an edge case situation where the next rank was not available. Not really sure what caused it to be missing, but this prevents issues from happening within prison. + + +* **Improve how bypass resets works.** +Fine tune the bypass resets so it works better. Found some issues & fixed them. + + +* **Added 3d distances to some mine related commands** +Added the distance the player is from the mine to the /mines info command. +Created a 3d distance function to use for displaying distances to the mine. +For mine related messaging, its using 2d distances, ignoring the Y axis. + + +* **New Feature; Slime Block Fun!** +Simple feature to add some bounce to the Prison fun! +Different items in hand increases boost. After jumping on a slime block, the player gains immunity from fall damage, but they can still die if they land in lava, the void, etc... +Not really sure what the life span of this will be? +To enable, set the configuration property "slim-fun" to true in plugins/Prison/config.yml. + + +* **New Features: Command /mines list now has paging! Plus useful sorting.** +Major changes to the /mines list command by adding paging and better to read formatting. +Now you can specify a page and be able to read what's in the list. In game you can click to page to other pages. +This listing is sorted by Blocks Mined (since last server restart) then by Mine Name. This help to put the more active mines on page 1 and the inactive ones at the bottom of the list +There is an option for pages of ALL so you can get a full dump. If you want it. + + +* **Minor refactoring: Remaining Time before the Mine Resets** +Moving the calculations for the remainingTime in to the core mine classes so it can be accessed by other functions. This also moves the business logic out of the MineManager and puts it in the mine, where it should be. + + +* **Typo fix: Noticed a field was named "Rest" instead of "Reset".** +The fixing of the name does not alter the behavior of the code, but the wrong name could confuse someone. + + +* **New Feature: New Mine Placeholder! Mines Reset Count.** +Added a new mines placeholder: Mines Reset Count. Identifies how many times the mine was reset since the last server restart. + + + +* **New Feature: Zero Block Mine Reset Delay** +Added a new parameter to mines for a mine reset delay when the mine reaches zero blocks. + + +* **New Feature: Setup a packaged paging system for the commands** +New feature: Created a new class to encapsulate multiple pages for commands. Based upon /mines block search and hooked it up to /mines info. +Provisions for pre-pages that are shown before the listings, such as the first page of /mines info. Will expand to other commands later. + + +* **Bug Fix: If BlockType does not exist use STONE instead** +Bug fix: Found a problem that if you put a Block Type in a mine that does not exist on the server it fails to reset the mine and there really are no errors shown in game. +Default to STONE if the material does not exist. + + +* **New Feature: New Placeholder for mines. Blocks Mined!** +Added new placeholder blocks mined. This reports on the total blocks that have been mined within a mine since the server restart. + + +* **Improved Performance: AutoManager by extending from OnBlockBreakEventListener** +Extend the AutoManager so the same BlockBreakEvent logic for cacheing the player's last mine used to optimize performance. +By extending the class, and creating the doAction() function allows for simple reuse of the event listener. +It is also critical that the AutoManager is able to set a LOW event priority. + + +* **Improved performance: for the onBlockBreak event listener** +This is the code that monitors the number of blocks remaining in a mine. This logic will also be applied to the auto features since it needs to perform the same basic initial setup and checking to ensure the blocks are within a mine. + +Significant improvements to the OnBlockBreakEventListener to try to minimize overhead and to improve individual performance for all players. +The biggest hit, performance wise, will be when mining outside of the prison mines since it would have to check to ensure it's not within a mine, and will go through the whole list. It's just simple math, but performed for each mine that exists so it will add up. +Overall, the overhead is not much, but efforts were made to reduce it as best as possible, of which, I think is the best that can be done with the current environment. +Also renamed addBlockBreakCount function to incrementBlockBreakCount since that's what it is doing. + + +* **New Feature: Hooked up auto mine reset when blocks remaining reaches zero** +When a mine reaches zero blocks left, then it will auto reset. +This is hooked in to the onBlockBreak monitor and all it does is cancels the current mine's reset and then resubmits it to reset. +This could allow for the creation of a one block grinder. Although there may need more work, such as delays to slow down the reset since it is able to reset at blistering speeds. + + +* **New Feature: Enabled the blockBreakCount feature** +Using the new blockBreakCount feature on the placeholders to eliminate the use of the old refreshAirCount() function. +This should provide a lot of performance improvements and will allow for live updates without much overhead on the server. + + +* **Internal Mine Optimizations** +Refactored a lot of stuff with mines to eliminate wasteful operations. +Setup a collection organized by name for quicker access when there are larger number of mines within a prison. +Changed remove block to remove ONLY the first block so as to help admins remove duplicates instead of having to go back and readd them. Fixed issue with missing not on if blocktype is in mine. +Cleaned up the save mine function in relationship to the initial loading of mines to simplify the code and to eliminate possible problems. + + +* **New Feature: Starting to track actual block breaks in mines** +Hooked up an even monitor for BlockBreakEvents to track them within each mine. +This is a work in progress to eliminate the counting of air blocks, of which could be a strain on the server if something like holographic displays is hooked up to each mine, and runs a few times per second. +Upon server startup, had to count air blocks, but changed it to sync since on server load it was throwing too many exceptions due to entities within those chunks. +Hooked up a temp placeholder to test with, which will be removed shortly once moved in to production. + + +* **Async issue: Mine air counts** +Async failure: Well, found out the hard way there is even less that can be done with async threads. Even just checking the air counts that does not update the world can cause problems and could throw an exception. +The issue is that if a chunk has to be loaded and if there are any entities, then it will throw an exception and could possibly corrupt something. +For now i'm catching the exception and logging it. Will eliminate the async air counting in the next few days when I hook up live block counts of mined blocks. + + +* **Clear coordinates after usage** +Made changes to ensure that the coordinates are cleared after they are used. Also same for the last used mine name when that mine is deleted. + + +* **Enhancement: Better logging if major failure with rankup** +Enhanced the logging on rankup to better deal with logging even when there is major internal failures. Emphasis was to ensure transaction logging happens and is recorded no matter what. Added more details and fixed a few that were not working correctly. +Fixed a failure that was preventing rankup from happening. Had the wrong conditional testing that was preventing a rank from being assigned. + + +* **Enhancement: Placeholders optimized!** +The placeholders without the prison prefix have been eliminated since the prefix is now prefixed when it is missing prior to matching to a valid placeholder enum, and when generating PlaceholderKeys. This cuts the number of generated placeholders in half. This is significant since with the addition of the aliases there would be about 744 placeholders generated if the prison had 30 mines setup! Now a 30 mine prison would have about 372. + + +* **New Feature: Placeholder aliases!** +Added shorter versions of all placeholder commands. The aliases still must be prefixed with prison_ and if it's a mine related placeholder, then it must end with _minename. +Aliases are also displayed on the /prison version page in parenthesis following it's original placeholder name. + + +* **New Feature: Added a new placeholder! prison_rankup_cost_percent** +This indicates how close a player is to ranking up based upon their balance and expressed in percent closeness. +If their balance is zero or less, it will show zero percent. If they have more than enough money then it will show 100%. + + +* **New Feature: Added an auto rankup for all new players to the server!** +Added a rankup to the default rank on the default ladder for when a new player joins the server. +I REALLY thought this already existed!! oof!! +Modifed the rankupPlayerInternal function to supply the default ladder and default rank if needed. Also added more logging transactions to cover the new events. + + +* **Enhancement: AutoManager's BlockBreakEvent had to be set to a lower event priority** +Had to set to a EventPriorty.LOW so other plugins can work with the blocks. The other plugins were EZBlock & SellAll. This function was canceling the event after it auto picked it up, so the other plugins were not registering the blocks as being broken. The default EventPriority was originally set to NORMAL and that was not working with the other plugins. So setting it to LOW allowed them to inspect the block that was being broke, and do what they had to do, before prison's AutoManager performed the auto pickup events with it. + + +* **New Feature: Auto features added: Auto Pickup, Auto Smelt, and Auto Block!** +Gabryca added auto features to Prison. They include auto pickup, auto smelt, and auto block. + + +* **New Feature: Added detailed reporting on rankup, promote, demote, and set rank** +Added detailed logging on rankups to track all details. It may appear to be overly detailed, but if something goes wrong, it will allow tracking down exactly what may have went wrong. + + +* **New Feature: Added support for GemsEconomy and Custom Currency** +Added a direct integration for GemsEconomy so Prison can now use a custom currency with Rankups. +Added within prison the support for custom currencies. There is a special mechanism in place for dealing with custom currencies, since it requires special interfaces to specify the currency. Prison checks to make sure there is not only a registered economy that supports custom currencies, but it also checks to make sure the currency that is specified within the ranks is supported by an economy before allowing the player to add it. It also checks to make sure all custom currencies have supported economies upon Prison startup and reports errors if they are not found. When a player attempts a rankup, everything is once again checked to make sure the economies support the custom currency. Prison provides for admins to bypass the use of defined custom currencies through **/ranks promote**, **/ranks demote**, and **/ranks set rank**. + + +* **New Feature: List currencies that are used in Ranks** +On startup, gather all currencies that are defined within all of the Ranks, confirm there is a economy that supports it, and then print the list with the ranks module. If a currency is not found, then print an error message on the Prison start screen. The currencies will then be listed with each of the supporting economies when doing the /prison version command. + + +* **New Feature: Added temporal references to to the next lower and higher ranks** +To provide a much more simplified way of getting the next higher and lower ranks +when you already have a rank, I added temporal references internally to the ranks. +This means there is a zero cost associated when trying to get the next higher or lower +rank and its as simple as just another field within ranks. +These references, because they are temporal, are realigned when the ranks and ladders +are initially loaded, and whenever ladders change. + + +* **New Feature: Added base commands to /prison version listing** +Added the base commands to the /prison version, which is tied to the modules. +If a module is successfully loaded, then it will show the base commands that +it supports. + + +* **New Feature: GemsEconomy Direct integration** +Starting to hook up GemsEconomy. It's not ready and it may take a while to +put everything in place. The major thing that GemsEconomy provides is support +for non-standard currencies. + + +* **New Feature: AutoManager** +Gabryca is adding this new feature to the spigot interface. + + +* **Upgraded API: EssentialsX v2.1.7.1.0** +Update to the most recent version of EssentialsX v2.1.7.1.0 was v2.0.1-b354. +This is an internal library used only for compile purposes. + + +* **Upgraded API: SaneEconomy v0.15.0** +Update to a more recent version of SaneEconomy v0.15.0 was v0.13.1. +Note this is the last version where the signature of getBalance and setBalance is using doubles. Newer versions use BigDecimal so I've put try catches around them to capture potential errors so it can be reported. Did not upgrade to anything newer since the backend storage has changed which may be a major change for some servers. +This is an internal library used only for compile purposes. + + +* **New Feature: List all registered plugins** +To better support server owners when they have issues with Prison, the command +**/prison version** now lists all registered plugins along with their versions. +With this feature, to provide the information we need to help trouble shoot, +they only need to copy and paste to provide all the information we need. +"Please copy and paste the full **/prison version** command listing." + + +* **New Feature: prison_rankup_rank_tag added** +This provides the tag of the next available rank. + + +* **Started to Add Documentation** +To help ensure all users have access to Prison's documentation, and to be able to version all documentation, I've decided to go with github markdown documents. This will allow the documents to live within the project and they will be accessible online through github. Simple markdown hyperlinks will tie them together so the user can browse them by just clicking links to navigate. Markdown is very limited in what can be done with it, but accessibility and versioning is more important than bells and whistles. + + +* **Pulled in the Prison GUI menus** +Pulled the prison gui branch in to the bleeding branch. This was the result of the awesome work by Gabryca. +I added the mapping of /prison gui to redirect to /prisonmanager gui so it's integrated +with the standard prison commands. +Added the new permissions to the plugin.yml file. + + +* **New Feature: Mine Placeholders** +A lot of code was rewritten to support the mine related placeholders. Player placeholders +are simple since there are just a few placeholder keys. Mines are far more complex since +you have the "basic" internal placeholder keys (names), but when exposed outside of +prison, the mine names must be super imposed on each one. So if 6 mine placeholders +exist, and the server has 40 mines, then it would have to generate 240 placeholders. +Then it has to map all of those placeholders back to the internal placeholder key, so +it can identify which action to take. +Hooked the six new mine placeholders to their proper functions. +Created a mines chat handler. +Updated the player chat handler to use the new formats. Also updated MVdWPlaceholderAPI +and PlaceholderAPI to handle the new mines placeholders. + + +* **New Feature: Add in the target reset time for the mines** +This correctly sets the future targetResetTime when the next workflow job is submitted. This auto-adjusts the target time to compensate for delays in the system. +It also detects if there was a change in the reset time for the mine, and if so, then it will regenerate the jobWorkFlow to reflect those changes. + + +* **New Features: future targetResetTime, player counts within a mine, and count air blocks** +Start to hook up some mine related features such as future targetResetTime (the project time in the future when the mine will reset). This allows the creation of a count down timer until the reset happens. +Add a function to count the number of players within a mine. +Added a set of function to count the number of air blocks in a mine asynchronously. Set it up as a submittable task. The airblock count buffers and will run only every 30 seconds at most. If its a large mine, then it will delay slightly longer before refreshes to conserve computational resources. + + +* **Bug fix: Mine data was not fully loading prior to submitting workflow** +Found a timing issue where the mine's workflows were being submitted before all of +the mine related data was loaded from the file system. Over all it did not cause +too many issues, but it was defaulting back on the default values for mine resets +and was ignoring what was set for that mine. I implemented an inititialization +"channel" in the mine stacks... basically all layers of the mine's hierarchy will +kick off their constructors from the bottom (MineData) to the top (Mine). Once all +the layers are instantiated, then it kicks off executing all of the initialization +functions from the bottom (MineData) all the way back up to the top (Mine) again. +This allows the full loading of the saved mine data at the top layer, Mine, and then +allows a lower layer to utilize that loaded data, such as submitting the workflow. +This simplifies a lot of complexities pertaining to chicken-or-the-egg timings. + + +* **Compatibility Fix: Conflict with another chat plugin** +There was an onPlayerChat with the AsyncPlayerChatEvent issue +with the plugin InteractiveChat that was resulting in intermittent issues where +placeholders and on hover events were not always firing or working correctly. +Issues were resolved when the prison plugin was removed from the server that was +having this problem. +Reviewed the prison code and everything looked good, but what got things to work +correctly was setting the Spigot onPlayerChat event priority to EventPriority.LOW. + +* **New feature: /ranks set rank **. +You can now just set a rank on a given ladder, and not have to worry about multiple +promotes or demotes. +**Caution:** Use carefully, each rank that is configured must be independent of all the other +ranks. In other words, a given rank cannot expect the lower ranks to have set some +specific permission, but each rank's commands must ensure it works correctly without +hitting all the lower ranks. Same goes for when this command is used for demotions +and skipping many ranks in the process. + +* **New Features: Offline player support.** Added off line player support on some of the +commands. This now allows working with the players even if they are offline, which was not +possible before. + +* **New Features: /ranks promote and /ranks demote.** This is a way for an +admin/owner to demote or promote players directly, without incurring a cost to +the player. +This is good for testing purposes. But has a major concern. When setting up +the rank commands, the commands to remove elevated permissions must also be +included. Otherwise if a player is demoted, their perms will not be removed. + +* **Tag with v3.2.1-alpha.5 and add Core Documents shells** Started to +put together the document structures within the project. NO content yet, +but trying to hook everything up to the table of contents. More to follow! + +* **Removed Feature: Disabled the Sponge build**. The sponge project +was getting to the point that all the key functions that prison needs, has +no code and were returning nulls. Did not test the latest sponge build, +but there is no way some vital aspects would work, such as mine resets. +So commented the sponge references from gradle config files so it can be +easily reenabled if anyone wants to try to hook it back up in the future. + +* **Added command placeholders to display**. When the user is entering the +command **/ranks command add** it will now display the command placeholders +as {player} and {player_uid} so the admins/owners won't have to keep +asking what they are. They actually need to be displayed elsewhere too: TBD. + +* **Bug Fix: Glass block was not being removed** when fill mode was +enabled. Glass block will now be replaced as expected. + +* **New Feature: Mine Reset Notification Control** On a per mine +basis, notifications can now be turned off, set to a radius area from +the center of the mine, to player who are properly within the mine. +Added a command to support this new behavior: **/mines notifications**. +Each mine is independent, and there will be no global values. +As new mines are created/added they will be set to the default +radius distance which is currently 150 blocks from the center of +each mine. + +* **Bug Fix: Added PlaceholderAPI to the softdepends** Paper server +environment identified that it was missing. So I added it. Not sure +if that could have been cause issues with Multiverse loading issues? +Doubtful, but this is the first "thing" that has been found related +to hard depends or softdepends. + +* **New Feature: Command /mines resetTime** Added the command to allow +users to change the reset time for each mine. The global reset time is +only applied to new mines that are added. The new times apply once the +mines reset at the next mine reset. + +* **Work in progress: Mine resets** Committed the WIP just to get +it in git. Currently the code works, for that of which is being used. +The more complex compoennts dealing with async and paging is not yet +enabled so will have no impact yet. Also needed to commit so I can +add new features that overlap with this work (notifications). + +* **Removed dead links in README.md** A user made a reference to a few +dead links so I removed the ones that I could find. Also removed the +request for donations since that's currently a moot point. + +* **Took a quick look at tab completing" but ran in to issues with how +prison uses multi-word commands The space appears to force everything that +follows to be treated as an attribute/parameter to the root command. +Special handling of these conditions will need to be addressed later. +Tabled this attempt with hopes to return to it soon. + +* **Added new placeholder tag: prison_rank_tag** The existing placeholder +**prison_rank** returns the name of the current rank for the player. +The new placeholder **prison_rank_tag** returns that rank's tag value, +which could include formatting characters and would be suitable for +text chat prefixes. + +* **Bug Fix ?? : Cannot manually edit rank and ladder files.** +(to be addressed) +Manually editing the rank and ladder files, and maybe even the player +files, does not work, even when the server is shut down and restarted. +Could not reproduce, but a couple of users reported this as an issue and +I think I saw it once before too. Not really sure the cause but did not +see anything obvious in the code either. + +* **Bug Fix: Players on server prior to setting up prison have no ranks** +(to be addressed) +When prison is setup initially, if a player is already on the server, they +will not be assigned a player rank. This causes failures when the player +tries to use the /rankup command in that it reports "Error ! You don't have enough +money to rank up! Then next rank costs !" This happens when the rank +costs zero. + +* **Bug Fix: Found issue with the Vault Integration for Economy** +The vault economy integration was wrong. It was mixing use of player-centric and +bank-centric processing. As such balances may not have been working consistently, +and many of the vault's supported economys probably were failing to work at all. +This fix allows it work correctly and will eliminate possible failures and +intermittent issues.t + +* **Improve the reporting at startup and also for /prison version** +Added more details to provide the user with more information about +the prison environment and also the integrations. It's a work in +progress and some of the current formats will be changing and will be +refactored to be more useful and easier to read. + +* **Bug fix in third party tool: Rewrite of the SpiGet version reporting tool** +Bug fix. Third party tool. Spiget "claims" it deals with semVers when +that is nothing even close to being true. I wrote a proper version +parser to use for Prison so semVer actually works correctly which will +hopefully eliminate some situations where it fails. +I may fork the spiget project in the near future and share this +code with that project so others can benefit from proper semVer +handling, which may address some of their open issues too. + +* **Added new bStats parameter - Mines, ranks, and ladder counts** +Added a new custom parameter to bStats to record the number of mines, ranks, and +ladders that has defined at startup. So this data may now be added as custom +charts, but may not be able to ever see it online since I do not own the +bstats online account to configure it correctly on that end. But at least the +data will be there if it's even enabled. + +* **Added /ranks player command** +New command /ranks player show what rank a player currently has. The player must +be online. Future could add support for offline players, but quick attempt to +hook that results in some internal failures within the Prison plugin so deferring +on that feature. + +* **Change How Integrations Work** +All directly accessed integrations are now logged and recorded so their status can be +included with the /prison version command. Integrations that are indirectly used, +such as through other plugins like Vault, are never listed directly unless Vault +references them. + +I went though the placeholder integrations and fixed their APIs to use the newer +set of place holders. Fixed some bugs and expanded features. The list of integrations +now also includes the primary URL where they can find more information on the plugins, +and where to download them from. Also provides some additional information, such as +available place holders that can be used. + +* **Added Minecraft Version** +Added minecraft version to be stored within the plugin so it can be displayed +in /prison version and also be used +in the future with selecting block types that are appropriate for the server version +that is being ran. + +* **Bug fix: Block types not saving correctly if depending upon magic values** +Found an issue where loading blocks were by the BlockType name, but saving was by the +minecraft id, which does not always match. As a result, there was the chance a block +type would be lost, or it would revert back to the generic such as Birch Block +reverting back to Oak Block. + +* **Need to update gradle - Was at v4.10.3 - Upgraded to v5.6.4** +Currently this project is using Gradle v4.10.3 and it needs to be updated to v5.6.4 or +even v6.0.1 which is the current latest release. It was decided to only take the project +to v5.6.4 for now, and wait for the next release on v6.x, which may gain more stability? +But to do that it must be incrementally updated to each minor version and you cannot just +jump ahead or there will be failures. At each step you need to evaluate your build scripts and +then make needed adjustments before moving onward. + + * **Versions Upgraded To:**: **v5.0**, **v5.1.1**, **v5.2.1**, v5.3.1, v5.4.1, v5.5.1, **v5.6.4**, + * **Versions to be Upgraded To**: v6.0, v6.0.1 + * gradlew wrapper --gradle-version 5.0 :: Sets the new wrapper version + * gradlew --version :: Will actually install the new version + * gradlew build :: Will build project with the new version to ensure all is good. If build is good, then you can try to upgrade to the next version. + * Update to v5.0 was successful. Had to remove enableFeaturePreview('STABLE_PUBLISHING') + since it has been deprecated. It does nothing in v5.x, but will be removed in v6.0. + * Update to v5.1.1, v5.2.1, v5.3.1, v5.4.1, v5.5.1, v5.6.4 was successful. + + +* **Minor clean up to Gradle scripts** +The "compile" directive is actually very old and was deprecated back around version +v2.x. The replacements for that is "implementation" or "api" instead. The use of +api does not make sense since its use is to tag when internal functions are exposed +to the outside world as if it will be used as an externally facing API. That +really does not fit our use case, but what api also does is to force compiling all +source that is associated with something marked as api, including everyone's children. So performance will suffer due to that usage, since it shuts down incremental +building of resources. + +I also found that use of compileOnly may not be used correctly, but at this point +I'm just leaving this as a mention and then revisit in the future if time +permits, or issues appear to be related. Its a very old addition that provided +gradle with "some" maven like behaviors. It was only intended to be strictly used +for compile time dependencies, such as for annotations that are only needed for +compile-time checks, of which the plugins and resources we have marked as +compileOnly do not fit that use case. +[discuss.gradle.org: compileOnly](https://discuss.gradle.org/t/is-it-recommended-to-use-compileonly-over-implementation-if-another-module-use-implementation-already/26699/2) + + +* **Redesigned mine block generation works - Async and paged enabled** +Redesigned how prison blocks are generated to improve performance and to allow the +asynch generation of blocks, but more importantly, allows for paging of actual +block updates. The paging is a major feature change that will allow for minimal +impact on server lag, even with stupid-large mines. The idea is to chop up the +large number of blocks that need to be regenerated in to smaller chunks that can +be performed within one or two ticks, then defer the other updates to the future. +Thus freeing up the main bukkit/spigot execution thread to allow other tasks +to run to help prevent the server from lagging. + +* **Support for LuckPerms v5.0.x** +In addition to supporting older versions of LuckPerms, Prison now is able to +integrate LuckPerms v5.0.x or LuckPerms v.4.x or earlier. Take your pick. + +* **Minor changes to reduce the number of compiler warnings** +Minor changes, but better code overall. + + +* **Improved mine regeneration performance by 33.3%** +Figured out how to improve performance on mine regeneration by roughly about 33.3% overall. This +could help drastically improve performance and reduce lag since block updates must run +synchronously to prevent server corruption (limitation is due to the bukkit and spigot api). + +* **Mine stats and whereami** +Added a new command, **/mines stats**, to toggle the stats on the mine resets. Viewable with **/mines list** and **/mines info**. Stats are now within the MineManager so it can be accessed from within +the individual mines. +Added a new command, **/mines whereami**, to tell you what mine you are in, or up to three mines you are nearest to and the distance from their centers. + + +* **Major restructuring of how Mines work - Self-managing their own workflow** +They now are able to self-manage their own workflow for sending out notifications and for resetting automatically. +Mines is now layered, where each layer (abstract class of its ancestors) contributes a type of behavior and business logic that allows Mines to be more autonomous. +As a result, PrisonMines and MineManager are greatly simplified since they have less to manage. +Because Mines are now self-managing their own workflow, and they have taken on a more expanded role, some of the mine configurations are obsolete and removed. +Mines only notify players that are within a limited range of their center; they no longer blindly broadcast to all players within a given world or the whole server. +Mines extend from MineScheduler, which extend from MineReset, which extend from MineData. Each layer focuses on it's own business rules and reduces the clutter in the others, which results in tighter +code and less moving parts and less possible errors and bugs. + + +* **Concept of distance added to Bound objects** +Added the concept of distance between two Bound objects so as to support new +functionalities between mines and players. + + +* **Gradle now ready to upgrade to v5** +Resolved the last few issues that would have caused issues when upgrading to gradle +v5. Explored how gradle can use java fragments and variables. + + + diff --git a/docs/prison_changelog_v3.2.2.md b/docs/prison_changelog_v3.2.2.md new file mode 100644 index 000000000..f60f4f232 --- /dev/null +++ b/docs/prison_changelog_v3.2.2.md @@ -0,0 +1,725 @@ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +# Prison Build Logs for v3.2.2 - 2020-11-27 + +## Build logs + - **[v3.2.3-alpha - Current](../changelog_v3.2.x.md)** + - **[v3.2.0 - 2019-12-03](prison_changelog_v3.2.0.md)** + - **[v3.2.1 - 2020-09-27](prison_changelog_v3.2.1.md)** + - **[v3.2.2 - 2020-11-21](prison_changelog_v3.2.2.md)** + + +Greetings! I'm delighted that you are interested in the build logs for the +Prison plugin. I'm wanting to provide a more formal documentation as to what +is going on in each build so you have a better idea if it may be something +that you need. + + + + +# V3.2.2 Release - 2020-11-21 + +This version is being released to fix outstanding bugs and to provide a better end user experience. Preparing for a few other changes, so want to get this released before possibly changing the stability of any feature. + + +* **v3.2.2-alpha.14 - 2020-11-21** +Bump version... preparing for v3.2.2 bug fix. + + +* **Refactored where the commands that are outside of the modules are registered.** +They are now registered within the function where the modules are registered to allow the related commands to either be registered or not, based upon the modules. +Refactored how some of the commands/configs are setup to be more flexible, or to better follow the standards of how prison has been instantiating them (ListenersPrisonManager). + + +* **Split out the gui ranks and gui mines commands** from the main spigot gui commands. This allows them to be enabled on their own, or more importantly, prevent them from being registered if the modules are not loaded. + + + +* **Changes to the gui commands to prevent console from running a few gui commands.** +Also remove the alias of "prisonmanager" for "gui". +It was reported that when a non-admin tried to use /mines that it was giving the error message associated with /gui. Cannot see a direct relationship there, but hard linked /mines to /gui mines by calling the function directly instead of resubmitting the command. Not sure if this fixes the issue, but I was unable to reproduce it. + + +* **Minor changes** +Add more to the BaseCommands and start to hook them up. Fix usage of getting the current economy. + + +* **To prevent prestige related commands from being registered with bukkit**, +pulled prestige related commands in to their own command class and then conditionally register them if prestiges are enabled. Cleaned up a few other things such as remove use of deprecated functions and +moving the implementation of isPrisonConfig to SpigotPrison to simplify a few things and eliminate duplication. + + +* **Fixed a problem with bukkit on a paper v1.16.4 server where the Bukkit.getOfflinePlayers() was returning either a null player, or a player had a name that was null.** + + +* **v3.2.2-alpha.13 - 2020-11-15** + + +* **Updates to the GUI: many.** +Moving configs to a common package to better manage them, or to prepare to merge them in the future. Many other fixes and enhancements. + + +* **Updated the SpigotMineBlockPercentageGUI to include a Close button and to show the selected block top and center.** +Also provided links back to the block list gui. Setup the parameters to return back by setting the font color to black so it is visible that they exist as the players hover. + + +* **Fixed issue with GUI block list.** +Using a combination of XMaterial and ItemStacks, its able to display the viewable blocks. Added Prior button to go back to prior page. Got the Next page button working (it was incorrectly just blindly deleting the first two characters of the button name; changed it to strip color so it is not destructive. Setup this page to be able to return to it from other pages. Confirmed that this works with spigot v1.8.8 and spigot v1.16.3. + + +* **Fix issue with GUI not being able to display red or lime stained glass panes** +due to use of material instead of ItemStacks. This applies to mc v1.8 through mc v1.12 and they display as plain glass panes (no colors). + + +* **Added a SpigotPrison function to strip all colors from text.** +Needed in the GUI to hide extra parameters. + + +* **GUI direct support for ItemStacks when creating buttons for mc v1.8 through mc v1.12. ** +With the use of magic numbers with Minecraft versions less than 1.13 the use of Materail to create ItemStacks fails to get the correct type if magic numbers are involved. Created a new createButton function to work directly with item stacks so the proper blocks can be used with mc v1.8 through v1.12. + + +* **Additions to PrisonBlock handlers to provide more utility functions** +and to solve a few complex challenges. Removed NULL_BLOCK from the valid block lists. + + +* **Found function names that started with capital letters and changed them to lower case.** +Function names should never be capitalized since that would imply they are classes, or similar objects, and not functions. + + +* **Compile error with the removal of the prison core gui...** +Removal of this code was forgotten when removing the prison core gui code. Not sure how that passed the compiler before committing to git? + + +* **cleaned up unused imports in the gui code; were causing compile warnings.** + + +* **New feature! Hooked the prison GUI up to the new prison command manager.** +Assigned aliases so as to preserve backwards compatibility with admins who are used to the prisonmanager command. +The /prisonmanager command has been replaced with just /gui. Tested and appears to be working well. Can do /gui mines, /gui ranks, /gui prestige, /gui prestiges. + + +* **Added /mtp as an alias to /mines tp.** + + +* **New GUI config system** +- It's an improvement. Has many code changes +- Deleted the GuiListener.java class, only SpigotPlatform was using it so nothing should break. + + +* **New Feature! Tab complete is now functional with prison's command handler.** +When typing in prison related commands, you can now press tab to complete the typing for you if there was only one option available, or it will fill in common letters until you need to make a choice. Also typing in a command pressing space then tab shows all available options. In game is slightly different that in console, where in game show a ghosting of the command where you are typing so tabbing will select that option. +Works on spigot 1.8 through 1.16.x. Also works in console. Functional with aliases too. + + +* **New Feature! Command Aliases!** +Add the complexities of supporting aliases in the prison command handler. Each command can have one or more aliases mapped to almost any level of paths. +This also includes a rich support of the sub-command and help listings to better identify which commands are aliases and also what aliases are available. There is room for enhancements that will be added soon. + + +* **v3.2.2-alpha.12 - 2020-11-10** + + +* **removed the trailing &f from the rank tag** +This was within the new feature /ranks autoConfigure. It was reported that there were issues within the plugin Scoreboard-r by RienBijl that data was being truncated and lost. Looking in to the issue it was found that there was a stray &f at the end of a tag. It had no impact, but it was removed anyway since it does nothing. It was determined that the scoreboard-r plugin is buggy and was causing errors. + + +* **New Feature: Now provides the capture of the actual label that a command is registered with Bukkit when there is a conflict.** The prison Command Handler now uses the registered label when displaying any of the sub commands or list of all registered root commands. This will allow the users to know what commands they actually have to enter to get them to work, instead of guessing when there is a conflict. + + +* **Improve block matching for pre mc v1.13.0** +For the 1.8.x material types in prison, there exists different states with the data value that could result in block types that are unknown. Some of it may be orientation or degree of flowing water, or even wetness of soil. I've seen it with leaves of different shades, or even with logs. +The idea here to fix this issue is not so much that we don't know the block type as much as it shouldn't matter the slight variations in the data field. Therefore if we fail to match on the id and data, then go off of the material name. That's a good fallback. + + +* **Bug fix: Fix incorrect display of no other mines near for /mines whereami** +If the player was standing in a mine and there are no other mines around, it used to show the mine they are in, plus say there are no other mines within 150 blocks. +Now it will not show the "no other mines in 150 blocks" message. + + +* **Mines Blocks GUI Fix** + + +* **Bug Fix: Found a bug in the command registration code** that could result in failing to properly register commands. This would have been an issue if there were upper case letters in a command, since all commands are converted to lowercase when added, but when checking to see if a subcommand was already processed (ie... the "set" in the following two commands: /mines set tag, /mines set resetTime). The symptoms would be missing commands at runtime. I actually have seen this failure in the past, and realized that all commands should be entered as lowercase due to this error. Now it should work correctly. + + +* **Clarify the role of a CommandHandler field that is used in a situation of when there is a command collision.** + + +* **Fix typo: In the /mines command add function, a & was placed one character to the right of where it should have been.** + + +* **Added an unregister all for the commands and hooked it up on the plugin's onDisable.** + + +* **Fixed issue with dropping of inventory.** +Had a ! where it shouldn't have been and forgot to hook up the new messageId variable so the warning can change. +I'm not so sure about messaging this way, using the action bar, but don't want to flood chat with a ton of messages either. Would have to put a limiter on the chat messages? + + +* **Fixed an index out of range issue in the gui.** +Was 45 when should have been 44. + + +* **New Feature: Added XP calculations to the block break (auto pickup) function** +which can be disabled. Give the option to drop the xp as orbs (default) or give it directly to the player with no orbs. + + +* **It was realized that dropItemsIfInventoryIsFull was not hooked up.** +Hooked it up. + + +* **Update some docs and added a few screen prints.** +Updates to a few documents to reflect some of the more recent updates to prison. + + +* **Updates to the IntegrationManager** so the variable is more consistent and especially the message for WorldGuard integration is clear that it is not an error that it is not yet active. + + +* **Change the command /prison alerts so they can be ran from the console** since it made no sense why the console was locked out from using them. +Slight changed the information for /prison gui that shows that it could be preferred to configure the autofeatures. + + +* **Changed the perms to lower case, specifically the mine/rank name. Should have been lower case.** + + +* **Had the wrong block name for dark_oak_planks (thought I fixed that already).** + + +* **v3.2.2-alpha.11 - 2020-10-29** + + +* **For /ranks autoConfigure: Almost forgot to add the removal of the mines.tp. when demoting a player.** + + +* **Added a new feature: can now set the area of a mine based upon location of your feet.** +This allows you to create a virtual mine, then set its location where you're standing or flying, then you can resize it. This bypasses the need of having to use a wand to create a mine or define it's size and location and allows it to be defined in mid air or in a void world where you cannot click on any blocks. + + +* **Fix the report on how many blocks are in a new mine.** It was reporting on surface area and not block count. +Fixed an issue with world being saved correctly. When a virtual mine was converted to a real mine, the world and world name were not always being updated. Fixed it by not only being more aggressive when setting the Bounds, but also when saving the mine. + + +* **Reenable the compatibility cache on block mapping.** +This eliminates related failures to map blocks, which will prevent wasted time continuously looking them up. + + +* **A few more tweaks to the block types to fix missing block from a pattern.** + + +* **Added the ability to add the "force" option to the /mines set liner command.** +Normally the command only adds the liner if there is not air so that the mine's liner does not extend above the ground level, and it ends at ground level. +Force is intended to cause the liner to work in a void area where all there is only air. Otherwise you would have to place blocks on the outside to "trick" the liner to work. + + +* **Fixed the block names for the new liner patterns.** +I accidentally added them based upon actual block names and not what is mapped to the prison block names or the new block types which are keyed to XMaterials. This fixed them. + + +* **Added a compatibility reference to help map it to XMaterials.** +Jungle_planks + + +* **Enhance the ranks auto configure by adding support for GroupManager permission plugin.** +Also added the remove permission of the next higher rank so as to support demotions. + + +* **Added three new patterns to the MineLinerBuilder.** + + +* **Minor code improvements for the player GUI and this should also fix the null value.** + + +* **The gui was trying to pass null strings to this format function.** +If the parameter value is null, then just return an empty String, otherwise try to format it. + + +* **Simplify the error message if a player does not have access to tp to a mine** +they should not be seeing anything pertaining to perms. + + +* **Hooking up more of the prison's mines commands to properly, and fully, use the new prison block model.** +The new PrisonBlocks are now being validated against the dynamic list of valid blocks that are available on the server that is running prison. So within the block search, as one example, it will only show valid blocks that can be used; the old block model would show all possible blocks within prison, some of which may not have been blocks. + + +* **Enhancements for Prison's new block model** +Enhance the PrisonBlock to use block instead of mineable for better consistency with bukkit and spigot use of blocks. Also set block name to be always lower case for easier searches. +PrisonBlockTypes has been enhanced to be able to search for blocks by name. This is using a b-tree for quicker retrieval instead of loop though all available blocks. +When valid blocks are added to PrisonBlockTypes (the valid blocks that exist on that server) they are have their isValid and isBlock values set to true. Also now using XMaterial names for better long term consistency that will not change if the admins upgrade or down grade their servers. + + +* **Hook PrisonBlockTypes up to the Prison object.** +This will load a list of new block types at server startup that have been validated against the version of minecraft that is running. This will ensure that the only blocks that the player will see listed in block searches, as one example, will be blocks they can actually use. This is highly dynamic based upon the server and not the complier. +This is preparing for the use of the new block model by giving access to valid blocks within many of the /mine related commands. + + +* **Remove more of the Items related code** which has not been used for awhile. ItemManager and troubleshooters related to that. + + +* **Reenabled the caching of null values when translating from one material type to another.** +This prevents looking up a failed code many times and only allows one error message to be logged to the console. + + +* **v3.2.2-alpha.10 - 2020-10-26** +Version bump due to the significance of the last bug fix. + + +* **Major bug fix: Eliminated the in prison caching of players.** +This collection was not able to deal with players reconnecting to the server, which would give them new player objects. The issue was that prison would have an obsolete (zombie) copy of the player and their inventory. So if any operations would be performed on the inventory, such as giving a selection wand, it would be placed in the orphaned object and the player would never get it. The only way to "fix" this issue would be to restart the server and then it would fail once they would log out and reconnect. +This was confirmed a problem with 1.9.2, 1.13.4, 1.15.2, and 1.16.3. It was not an issue with spigot v1.8.8. This did not impact players retrieved from events. +This fixes the issue by removing prison caching of the players. Now all instances of the players being used within prison are now live bukkit objects. +I suspect this issue has been within prison for a long time. Not sure why no one reported it before, or if they did, it was not clear how to reproduce this issue and the ones reporting it may not have been able to provide enough information to reproduce it. The way it is reproducable is to login, get a /mines wand or have prison interact with the player's inventory, then log out and then back in. Then /mines wand will fail to place it in the real player's inventory. It will only go in to the prison cache. + + +* **v3.2.2-alpha.9e - 2020-10-26** + +* **Bug fix: When a world is not available upon startup** it will try to set the boundaries for the mine. In doing so, it will try to extract the correct world to enable it and to remove the virtual status if it was set. If the world has not yet been loaded (ie... if you're using multiverse) then this was causing an error for that mine. This now will only mark the mine as disabled and allow the multiverse plugin to trigger the completion of the mine loading event for that mine (as it has been doing before virtual mines were added). +If a mine has the boundaries set and if it was disabled or virtual, then make it a real mine. Have checks to ensure the world is available, if not, then disable the mine. + + +* **v3.2.2-alpha.9d - 2020-10-26** + +* **New feature: Dump player's inventory to console** +This is useful to check status of various prison related functions. +One area that this maybe useful with some players reporting that they are getting a Prison Selection Wand, but it's not showing up in their inventory, although inspection of their inventory is showing they are getting it. + + +* **v3.2.2-alpha.9c - 2020-10-26** + + +* **Fix to GUIs and Close button conflict** +Fix to Mines GUI lore issues for Virtual Mines + + +* **v3.2.2-alpha.9b - 2020-10-26** + + +* **Fixes issue with not enabling a virtual mines** +when the area is set with the command: /mines set area help + + +* **Fixes to some blocks and use of XMaterial for STAINED_GLASS** +This allows for multi-version support since material names have changed at 1.13. This supports 1.8 through 1.16 now. This fixes an exception for versions less than 1.13. + + +* **Fixes to config, now you'll not see any "§" but only "&"** +There might be some strings that won't translate that, If you spot them (like lores with an & instead of color), please report it. This fixes an issue for some user's environment not being able to properly translate the `§` when generating the GUI config files and language files. Basically the file's UTF-8 encoding was being treated as ASCII and that character was being converted to a hex value that could not be translated back to something usable. + + +* **v3.2.2-alpha.9a - 2020-10-26** + + +* **Enable OPs to tp players even from console.** +Also if the player who is running the command is the same as the name being passed as a parameter, then allow it. + + +* **v3.2.2-alpha.9 - 2020-10-26** + + +* **Added the ability to move a mine but am not enabling it.** +It is not behaving as well as it should. The tracer is being left behind when it shouldn't. +Other adjustments to the sizing and liner functions have been made too. + + +* **Adjustments to getting the MineLinerBuilder working.** +These here are minor changes that makes a few aspects work slightly better. + + +* **Change the way the caching is working on block mappings.** +Removed the caching of no-hits on block conversions. Normally recording the no-hit conditions will result in significant performance improvements, but removed them for now to make sure they are not causing issues. Will have to reenable them (rewrite the code) in the future. + + +* **Provided more detailed reports on missing block types** +from spigot mapping to prison's old block types. Some of these will be needed until we can get the new block model fully functional. + + +* **Added a few new block types for v1.13.** +The major one that fixed some significant issues was GRASS_BLOCK since it used to be named GRASS in older versions of minecraft, but now GRASS is just the plant. +Also added 18 new log types for v1.13 and newer. + +* **Removed traces of the enableMineTracer within the Platform object.** + + +* **More improvements to the /mines set size and the /mines set liner commands.** +Added ladders to the liner, and also added repair to undo the liner based upon the surrounding blocks. Appears to be working well for spigot 1.8.8. + + +* **Rank Tags modified to accept spaces** +To match the capabilities of the Mine Tag, the rank tag was adjusted to allow spaces. The command /ranks set tag was also changed to remove the tag if desired. Also changed the /ranks create command to accept spaces in the tag name too. + + +* **v3.2.2-alpha.8 - 2020-10-22** + + +* **New Feature: Now able to line a mine based upon the selection of edges and patterns.** +This feature helps players to get up and running their prison a lot faster. +Many additional patterns can be added in the future. Supports 2d patterns that are from 1x1 to any larger size. + + +* **Bug fix? Needed to add TokenEnchant to the softdepend** +to prevent a java.lang.NoClassDefFoundError with the class com/vk2gpz/vklib/logging/ColorConsoleLogger. +Not really sure if I can call this a Prison bug since it appears to originate from within the TE API code base. But this works around their potential short comings. + + +* **Bug fix! Trying to format an already formatted item... oof!!** +This had everything to do with formatted currency amounts in placeholders. + + +* **Disabled the loading of the /items.csv file** +since that is obsolete and not working anymore. The items.csv file has been removed from the project since people were thinking they can just modify that file to add custom blocks. Nope... + + +* **Add logging to count how many blaze rods the player has before and after issuing the /mines wand command.** +there have been a few reports that it does not work, but I cannot reproduce the error. So this is step one in confirming if they actually get the blaze rod or not. +One possibility could be that another plugin is canceling the event so the player never gets the blaze rod. + + +* **v3.2.2-alpha.7b - 2020-10-21** + + +* **Temp pulled alpha.7** Someone said the were getting a lot of errors with this release. Hence the past two fixes. + + +* **Fix potential issue where the user tries to use a % % as escape characters when they should be using { } instead.** +It was causing a failure when trying to redisplay the text as for the % was trying to be used as a placeholder when fed through the String.format command. + + +* **New feature: /mines set size** +Can now adjust the mine size by specifying the edge and adjustment amount. Edges are top, bottom, north, south, east, west, and walls. +When adjusting the size, it automatically goes in to tracer mode so the mine's dimensions are easily seen. + + +* **v3.2.2-alpha.7 - 2020-10-21** + + +* **Created the code to add blocks to virtual mines when they are being generated with the /ranks autoConfigure command.** +Blocks are setup in a List with the least valuable to the most valuable. Then it's a sliding window of selecting blocks from the lowest mine to the highest ranked mine. The percentage per blocks are 5, 10, 20, 20, 20, 25 where the most valuable are least represented. + + +* **Added a few new blocks to prison's old block model.** +These are actually duplicates of what already exists, but these are instead named to mirror XMaterial names. The reason for this is to ensure consistency between the two block models used for testing. +Removed the items.csv document since it is not being used anymore and will only cause confusion if admins think they can add new blocks through that file. + + + +* **Added some internal reporting of the data contents.** +Most of this will be used with logging in the /ranks autoConfigure and also jUnit testing. + + +* **Error logging needs to throw these stack traces** since thats really the only way to get the details we need to fix the problem. +A throw was eliminated, but needs to be added back. + + +* **New Feature: Added 12 new placeholders including aliases.** +Added formatted placeholders for player's costs. Added a new placeholder for player balance. +Created a PlaceholdersUtil class to perform some common functions, such as formatting an amount to include a metric prefix. + + +* **tag v3.2.2-alpha.6a - 2020-10-19** + +* **Fix issue with mine name** +that is related to virtual mines if not creating a virtual mine. An extra space was added to the end of the mine name which was triggering an error message about spaces in mine names. + + +* **Add a second perm to allow mines.tp.** +to be added to each rank that is auto generated. +will provide support soon for EssentialsX warp... + + +* **New Feature: Allow the user to specify the material name in the GUI config files to use for a mine's block type.** +The material names are based upon XMaterial for consistancy throughout all versions of spigot/minecraft. +The format is: Options.Mines.MaterialType. + + + +* **New feature: produce a warning when the first parameter of any prison command is not a CommandSender.** +Parameters using Player has been causing stack traces under different circumstances because the prison command handler ALWAYS passes a CommandSender object as the first parameter, therefore that is the type it needs to be to prevent a method type mismatch exception. The new changes will provide a warning when starting prison; it should ideally be caught at compile time but it can't. + + + +* **tag v3.2.2-alpha.6 - 2020-10-19** Bump the version due to significant changes. +It needs more testing prior to being released to the alpha channel. + + +* **Bug fix: prevent the config files for gui and it's messages from loading from the file every single time it is accessed.** +And they were accessed everywhere, and for one message, even three to four times just to generate one message. +This should improve performance significantly for the gui overall. + + +* **Provide a way to get the counts of a given ModuleElementType.** +Allows for access in modules that don't have direct access to other modules. + + +* **Wrapping up changes on virtual mines** +Fixes issues with virtual mines. Allows full configurations of virtual mines except for setting the area and spawn point. + + +* **Bug Fix: Found the wrong parameter was being used on a few commands** +Fixes some hard to find problems where the wrong parameter was being supplied to the commands. It would work most of the time, but under some conditions it would fail. Was using a parameter of Player instead of CommandSender. + + +* **Added a logCore feature that does not try to translate colors...** +this helps to bypass exceptions if an exception is trapped. +Added a dump when parameters on messages are not properly paired. This will be critical when all messages will be externalized and subject to users messing up the formatting placeholders. + + +* **New feature! Auto generate Ranks and Mines!!** +This is based upon the work of Gabryaca, but I reproduced it to be a part of the RanksCommand and gave it the capability of generating virtual mines too! +This is actually a starting point of what it can become. I not only added the creation of mines, but I also hooked it up to link the mines and ranks together as it generates them. + + +* **Added a new command to the Platform... This allows the creation of a Rank or Mine based upon a ModuleElement.** +That has major impact on added flexibility, and could lead to an automation of generating mines and ranks. + + +* **Storing the rank commands within the PrisonRanks class.** +The allows internal access to the commands so they can be used internally too. Will be used for automation purposes. + + +* **Linked the various mine and rank commands to their respective managers** +so they can be easily accessed programmatically now. + + + +* **New Feature! Virtual Mines!** +Now able to create virtual mines. A virtual mine does not exist yet since it has no location, but you can configure all of the options first before setting the area with /prison set area. +This is phase 1 of this new feature. Not fully tested yet. +The intention is that when you auto configure all your ranks, it will also auto configure all your mines to go with those ranks. Then you can go back and set the mine's area as you build them. + + +* **Links the rank command commands to the rank commands so they can be used together.** +Setup createRank to return a boolean to indicate if the rank was successfully created. This will allow programmatic internal use of createRank to automate more features such as rank configurations. + + +* **Add mine commands to add ranks to mines, and to remove ranks from mines.** + + + +* **Added mines and ranks to the /mines info and /ranks info commands.** + + + +* **Added to the platform the ability to link mines with ranks.** +Individual ranks or mines cannot perform this action, but going through the platform can. + + + +* **New Feature! Added _/ranks setup_ and _/prisonmanager setup ranks_ commands.** +Now you can setup your default ranks in the default ladder with a command without +adding them manually for the first time, this command will add all Ranks from A to Z +and their rankupCommands executing the command that your permissions manager uses to add +a permission to the player to access to the `/mines tp ` command, the mineName +given by the permission have this format `mines.tp.` so you should make your Mines +with the same name of the rank, you can edit the `mines.tp.` for to another you want, like +`essentials.warps.` in the _guiconfig.yml_. +The supported permissions managers for now are: +- Ultra Permissions +- LuckPerms +- PermissionsEX +- zPermissions +- PowerfulPerms + + +## tag v3.2.2-alpha.5 - 2020-10-13 + + +* **New Feature!! Added new 20 new blocks to the old block model.** + v1.10.x: structure_block, magma_block, bone_block + v1.11.x: shulker_box - plus the 16 other colors that are available. + + +* **Bug fix: Prevent a NPE when no rank is assigned to the mine.** + + +* **v3.2.2-alpha.5c - 2020-10-13** Important bug fix. Need to bump alpha version soon. + + +* **New Features! Added 48 v1.12 blocks and 44 v1.13 blocks!** +V1.12 blocks: 16 colored glazed terracotta, 16 colored concrete, 16 colored concrete powder. +v1.13 blocks: 10 coral types, 10 coral block types, 10 coral fan types, and 10 coral wall fan types, cave_air, void_air, blue_ice, and bubble_column. + + + +* **Upgrade XSeries from v7.2.1 to v7.5.4** + + +* **New Feature!! Added the first Prison API components** +Started to add some api end points to make it easier to access some basic internals +without having to figure out how to conform to prison's restrictions. + + +* **Continuing work on linking mines and ranks...** +Mines and ranks are now being linked together upon server startup. +Not finished. There are still items to be added, like the mine and rank commands to work with adding and removing ranks and mines. + + + +* **v3.2.2-alpha.5 - 2020-10-11** + + +* **Cleaned up and standardized log levels.** +Added PLAIN for use with mine resets, and DEBUG too. Eliminated redundancies. + + +* **tag v3.2.2-alpha.4 - 2020-10-08** +Had to bump this to alpha.4 due to the new mine sortOrder being set to -1 if +the value is not found in the save files! This may cause users to panic. + + +* **New Feature: Initial work in linking Mines and Ranks.** +This is just the initial framework for the final product. Ranks have not been modified yet. + + +* **New Feature: New Feature: Add a warning if PlugMan is detected.** +It notifies the user that prison will not behave well and can be corrupted if PlugMan tries to reload it. +Also states we are not responsible for any corruption, nor are we obligated to help recover from said corruption. + + +* **New Feature: Added ability to send the ChatDisplay object directly to console log.** + + +* **New Feature: Added /ranks ladder moveRank** +since most people don't realize they can remove a rank from a ladder (it is not deleted) and then add it back in to another place within the same ladder, or another ladder. +This new feature just calls /ranks ladder remove and then /ranks ladder addRank. Simplifies the process and makes it clear to the user that the option is there. + + +* **Eliminated the listing of placeholders from /prison version** +since it was getting to be a really long list. +Provided a reminder on where to find the placeholders. + + +* **BUG FIX!! Found that the default value on mine sortOrder was being set to -1 instead of zero.** +This will suppress all the mines, but nothing will be lost. This value will be set upon initial +loading of the mines if they did not have that value set previously. + + +* **v3.2.2-alpha.3 - 2020-10-07** +Bump to v3.2.2-alpha.3 due to significant update to the Vault integration. +Have not heard anyone else has had issues, so may hold off on releasing v3.2.2 for a few days to add more updates. + + + +* **Bug fix: Had to make changes to which functions Vault is using based upon Vault's version.** +It appears like formerly deprecated functions have been disabled and does nothing now. +Made changes to inspect the version of vault that is being used, then properly target the correct function so it works properly with all versions of vault, including pre v1.4.0. +This bug fix is potentially a critical bug fix and may warrant publishing Prison release v3.2.2 to take care of this issue. + + +* **New feature: Added the player's current balance on the command /ranks player.** + + + +* **Bug fix: Found that the wrong amount was being refunded to the player when doing a /ranks demote with a player_refund.** +Works now, and the log entries are also correct. + + +* **Space missing in the display of the default rank for the command /ranks list.** + + +* **Bug Fix: A config file was being loaded many times to build one gui page.** +Moved the config to a class variable so it would only be loaded once. +This reduced the opening of a 39 mine GUI from 5.5 seconds down to 6 milliseconds for the offending function call. + + +* **v3.2.2-alpha.2 - 2020-10-06** + + +* **Updated the sorting of mines to simplify the sorting.** +Now the sort types either include or exclude the mines. There are no sort types that include all mines. But the function that performs the sorting based upon the sort type returns a collection that contains the included mines (sortOrder >= 0) and also a second collection that contains the excluded mines (sortOrder == -1). +The returned object, PrisonSortableResults, has helper functions to simplify integration in to the /mines list command. +The /mines list command now shows how many mines are included and excluded in that listing, and identifies what the other sort types will display the suppressed mines. + + + +* **New Feature: Setup the complex sorting on mines.** +Mines can now be assigned a sort order, with even suppressing mines from being included in the output. +Mines list can now be sorted in six different orders: alpha, active, and now sortOrder (user defined order), all of which suppresses mines with a -1 for the sort orders. Plus those but with including the suppressed mines. +The default being sortOrder, but if no mines have been configured, then they all will have a sortOrder == 0, and then all will be sorted alphabetically within that grouping. +Changed the prison's GUI to display mines in the sortOrder, with suppression of the -1 sortOrder values. +Added a junit test to test the generated sorting orders since they can be rather complex and should be tested at compile time that they are correct. +Note: In adding this new sorting, found where the bug was where the actual internal sort order was being altered. This is no longer the case and is fixed. + + +* **New Feature: Added Mine Tag Names and 8 new placeholders to support them.** +This is required for the future changes to support linking mines and ranks. + + +* **New Feature: Rename Mines. Bug Fix: Delete Mines.** +You can now rename mines. +This also fixes an issue with not being able to delete a mine: It deletes successfully, but is still active in memory. + + +* **Prison_v3.2.2-alpha.1d.jar - 2020-10-01** + + +* **Bug fix: change how /ranks list works with perms.** +Should allow all players to use this command since no-perm players can use /ranks and that just redirects to this command. +Removed admin features unless player has the ranks.list perm or they are op. The admin features are links to other internal commands. + + + +* **Potential bug fix if a config option does not exist** +Reformatted so the code will have a better chance of fitting on the screen without a bunch of horizontal scrolling... +plus got rid of a few instances of Objects.requireNonNull() which throws exceptions, which are not being caught. Which is also the wrong behavior to what we need here... if those configs are null, then instead of throwing exceptions, just move on to the next conditional in the if chain. +Should probably never use Objects.requireNonNull since it will crash prison and prevent intended functionality. This should probably be removed from elsewhere. + + + +* **New feature: Gui Languages Support** +New languages folder containing the GUI and future languages files so players can edit them or contribute to make a new +one with translations to download and put there, then you can select it by editing in the `config.yml` the `default-language:` +to the language of your area, this's also related to the file language name, +for example the name of the GUI messages file should be `GUI-en_US.yml` by default, so if you translate to another language +(for example italian) you should rename a new file to `GUI-it_IT.yml` and edit in the config.yml the string +`default-language: en_US` to `default-language: it_IT`, if you select a language file missing in the folder or invalid, +it'll be generated anyway using the default config as the model so it won't break the plugin, then you can translate it +later or edit the config to the correct one. + + +* **Prison_v3.2.2-alpha.1c - 2020-10-10** + + +* **Found an inconsistency in how the ranks are dealing with the document engine.** +Mines do not throw exceptions, but they were within ranks, which is not needed. + + +* **New feature: added some new 1.14 and 1.15 blocks** +Added some more new blocks since some of the 1.16 blocks appear to work in most circumstances. +Use at your own risk. +These blocks may not properly be spawned and may not be all blocks available for these versions. +v1.14 : BAMBOO, BAMBOO_SAPLING, BARREL, BELL, CAMPFIRE, CARTOGRAPHY_TABLE, COMOSTER, +FLETCHING_TABLE, GRINDSTONE, JIGSAW, LANTERN, LECTERN, LOOM, SCAFFOLDING, +SMITHING_TABLE, SMOKER, STONECUTTER, SWEET_BERRY_BUSH +v1.15 : BEE_NEST, BEEHIVE, HONEY_BLOCK, HONEYCOMB_BLOCK + + +* **Added a few v1.16 block types.** +Not sure if they will actually work. Obviously will never work with mc versions < 1.16. Use at own risk. +ANCIENT_DEBRIS CRYING_OBSIDIAN NETHER_GOLD_ORE BASALT POLISHED_BASALT +NETHERITE_BLOCK BLACKSTONE POLISHED_BLACKSTONE CHISELED_POLISHED_BLACKSTONE +NETHER_BRICKS RED_NETHER_BRICKS CRACKED_NETHER_BRICKS CHISELED_NETHER_BRICKS +CRIMSON_PLANKS WARPED_PLANKS STRIPPED_CRIMSON_HYPHAE +STRIPPED_WARPED_HYPHAE NETHER_WART_BLOCK WARPED_WART_BLOCK +LODESTONE QUARTZ_BRICKS RESPAWN_ANCHOR SHROOMLIGHT CAMPFIRE SOUL_CAMPFIRE +SOUL_LANTERN SOUL_TORCH SOUL_SOIL TARGET TWISTING_VINES WEAPING_VINES + + +* **Fix: Changed nether_brick to an item** + since this is an item and not a block. Added support so if it is found in a mine upon server startup, it will change it to a double_nether_brick_slab. + + +* **Prison_v3.2.2-alpha.1b - 2020-09-29** + + +* **Bug fix: Prison was allowing the material REDSTONE to be added to mines.** +This caused a failure during mine resets since that is not a valid block. That is redstone dust! +Fixed it so upon server startup, it will auto detect the use of this item in mines and convert it to REDSTONE_ORE. Thus the mine will work and won't disable the mine. +Also I changed the BlockType to Item so it's still there, but it cannot be presented as a block in the /mines block search tool. + + + + +* **Set new version to v3.2.2-alpha.1** 2020-09-27 + + + diff --git a/docs/prison_docs_000_toc.md b/docs/prison_docs_000_toc.md index 49c995574..ed70adf00 100644 --- a/docs/prison_docs_000_toc.md +++ b/docs/prison_docs_000_toc.md @@ -15,6 +15,12 @@ * **[Most Recent Version of Prison Documentation](https://github.com/PrisonTeam/Prison/blob/bleeding/docs/prison_docs_000_toc.md)** Docs change frequently, but GITHUG's master versions do not. These are the latest docs! +## Build logs + - **[v3.2.3-alpha - Current](changelog_v3.2.x.md)** + - **[v3.2.0 - 2019-12-03](docs/prison_changelog_v3.2.0.md)** + - **[v3.2.1 - 2020-09-27](docs/prison_changelog_v3.2.1.md)** + - **[v3.2.2 - 2020-11-21](docs/prison_changelog_v3.2.2.md)** +
# New! Prison Fast Start @@ -135,9 +141,8 @@ Prison now has a new set of features that can help you get up and running faster -* **Setting up Vault** - (coming soon) +* [Setting up Vault](prison_docs_016_setting_up_Vault.md) Including Vault is Strongly Suggested. - Hint: Download from spigotmc.org and copy jar to plugin folder. Zero setup. * [Setting up EssentialsX](prison_docs_0xx_setting_up_EssentialsX.md) - diff --git a/docs/prison_docs_012_setting_up_prison_basics.md b/docs/prison_docs_012_setting_up_prison_basics.md index b4d835409..060179695 100644 --- a/docs/prison_docs_012_setting_up_prison_basics.md +++ b/docs/prison_docs_012_setting_up_prison_basics.md @@ -26,13 +26,10 @@ There may be no hard dependencies that will prevent Prison from running, but the * **EssentialsX Chat** - Optional - Enhanced Chat experience. -* **EssentialsX Spawn** - Optional - Enhanced support for Spawns. - - * **A permissions plugin of your choice** - Required - Prison works with many different permission plugins through Vault. I strongly suggest LuckPerms since it is free and is under active development so bugs and performance issues will be addressed. * Warning: LuckPerms v5.0.x crashes older versions of prison, such as V3.2.0 and earlier. - * Notice: Prison v3.2.1 (including the pre-release versions) supports all versions of LuckPerms. - * Strongly suggest using LuckPerms v5.0.x with latest pre-release version of Prison. + * Notice: Prison v3.2.1, and newer, supports all versions of LuckPerms. + * Strongly suggest using LuckPerms v5.x with all of the latest versions of Prison. * **PlaceholderAPI** - Used through Vault, it is free and provides the core interfaces in to the usage of placeholders. Prison also has a special integration setup for PlaceholderAPI to register all of the Prison placeholders dynamically upon startup. You do not need to download anything from the cloud for prison to work with this plugin. @@ -48,20 +45,24 @@ Download Prison from [spigotmc.org's Prison History Page](https://www.spigotmc.o Setting up Prison is simple: -* Download Prison - Current Releases - - Go to the SpigotMC.org LuckPerm's resource page: +* Download Prison - Current Release + - Go to the SpigotMC.org Prison's resource page: - [Prison Downloads](https://www.spigotmc.org/resources/prison.1223/history "Prison download can be found under the Version History tab") - - Click on the Version History tab - - Choose the version to download + - Click on the Version History tab if needed + - Choose the latest version to download * **Download Prison's Pre-Release Version** - Useful to access newer features and fixes - - You can usually find a build on the Discord Server: + - You can always find the latest alpha build on the Discord Server in the #alpha-versions channel: - [Prison Discord Server](https://discord.gg/DCJ3j6r) -* Copy to your server's plugin directory +* Copy the prison jar file to your server's plugin directory. + +* Remove any older prison jar file -* Restart the server +* Restart the server. + +* Prison's startup information contains a lot of information. If you ever have issues, check that information first since it probably will identify what the issues are. * Follow Prison's documentation on customization, but at this point it's ready for use. @@ -131,6 +132,13 @@ On the startup screen, prison shows all of the base commands that are active. Fr * **/rankup** +If you use the command `/prison` it will not only display all of the sub commands available for `/prison`, but it will also include a list of all the other *root* commands and aliases that have been setup. + + +Prison Commands + + + These commands are intended to run in game, but most can be ran from the system console. Sometimes the system console is easier to displays longer listings, such as **/mines list**. Also the console is better with wider text, and with easier to read text since it's not trying to display over a mc world. diff --git a/docs/prison_docs_016_setting_up_Vault.md b/docs/prison_docs_016_setting_up_Vault.md new file mode 100644 index 000000000..1fb8d8a65 --- /dev/null +++ b/docs/prison_docs_016_setting_up_Vault.md @@ -0,0 +1,35 @@ + +### Prison Documentation +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +## Setting up Vault + +This document provides a quick overview on how to install Vault. + +Vault may be optional, but it is a very important plugin. It provides easy integration with economies and permissions. This is useful because its a standard way for prison to hook in and use any plugin that supports Vault. + + +
+ +# Optional Dependencies + +There aren't any required dependencies to using Vault, but Vault will be useless if there were no other plugins to hook in to it. + +The two most useful plugins to use would be EssentialsX and LuckPerms. EssentialsX is useful for its economy, and LP for the permissions. + + +
+ +# Setting up Vault + +Vault is simple to setup since there are no required configurations. + +* Download Vault: + - Go to SigotMC.org Vault download page + - [Vault Download Page]() + +* Copy to your server's plugin directory + + + +
diff --git a/docs/prison_docs_0xx_setting_up_EssentialsX.md b/docs/prison_docs_0xx_setting_up_EssentialsX.md index 18f8849ce..6c41ee280 100644 --- a/docs/prison_docs_0xx_setting_up_EssentialsX.md +++ b/docs/prison_docs_0xx_setting_up_EssentialsX.md @@ -26,22 +26,29 @@ Setting up Essentials is easy, but you've to choose which plugins to add. - [EssentialsX Download page](https://www.spigotmc.org/resources/essentialsx.9089/) * Unzip the download. * Copy the jar files of your choice to your server's `plugin/` directory. -* The zip file contains multiple jars of the same version. Always use the same versions with each other, but never mix one EssentialsX jar version with another version. -* Available Modules and what is recommended: +* The zip file contains multiple jars of the same version. Always use the same versions with each other, and never mix one EssentialsX jar version with another version. + + +* Available Modules and what is recommended and what isn't: * EssentialsX - Main jar - **Required** * EssentialsXAntiBuild - *Optional* - Don't use if using WorldGuard? * EssentialsXChat - **Recommended** - Provides chat based placeholders (see below) * EssentialsXGeoIP - *Optional* - Provide geo locations for players IP addresses * EssentialsXProtect - *Optional* - Not sure, but shouldn't be used with WorldGuard? * EssentialsXSpawn - *Optional* - Not sure, but provides special behaviors for spawn? Not sure. - * EssentialsXXMPP - *Don't Use* - Google XXMPP for spigot to confirm if you really have a need to use this. You probably never will. + * EssentialsXXMPP - *Don't Use* - Google _XXMPP for spigot_ to confirm if you really have a need to use this. You probably never will. + + +* Prison does not require you to change any settings in EssentialsX, but you may if you want to customize a few things. + -* Prison does not require you to change any settings in EssentialsX, but you may if you want to customize some things. * List of possible items to modify: * Chat prefixes (see below) * Item prices if you will be using the shop functions through EssentialsX. If you do, I suggest you remove the entries for armor, weapons, tools, food, etc. Otherwise players may accidentally sell things they need. Also you can add new items to be sold. * Customize kits * etc... + + * Restart your server
@@ -50,19 +57,21 @@ Setting up Essentials is easy, but you've to choose which plugins to add. ## Add the Prison placeholder *Rank Tag* to Player's Chat Prefix -* EssentialsX's plugin folder on the server +* Go to the EssentialsX's plugin folder on the server: + + * Path: `plugins\Essentials\` + + * Edit the `config.yml` file: - Search for the section pertaining to chat by using the keyword: **EssentialsChat** - Add the placeholders {prison_rank_tag} or {prison_rank} to the "format:" line. - * The placeholders should be entered in all lower case + * The placeholders should be **all lower case** * The curly braces is used by EssentialsX chat engine, not Prison. Other chat plugins may use percent symbols instead. * {prison_rank} is the rank name without special formatting * {prison_rank_tag} is the defined tag (with formatting) for that rank - Example: - ``` - format: '<{prison_rank_tag}:{DISPLAYNAME}>{MESSAGE}' - ``` + format: `<{prison_rank_tag}:{DISPLAYNAME}>{MESSAGE}` Reload EssentialsX settings, or restart the server. @@ -72,13 +81,21 @@ Reload EssentialsX settings, or restart the server. # Applying Settings and Reloading Essentials + * Restart the server. Or use **/essentials reload**. -* Notice: **Don't use /reload to reload the whole server!** Using /reload or another tool such as plugman could corrupt plugins. Prison was not designed to do soft reloads and as such mines, ranks, ladders, and even some player settings and histories could be corrupted. +EssentialsX -EssentialsX + +* If you reload essentials and the placeholders are not working, then you may have to either restart the server, or reload the prison's placeholders with the following commands, both of which are exactly the same: + - `/prison placeholders reload` + - `/prison reload placeholders` + + +* Notice: **Don't use /reload to reload the whole server!** Using /reload or another tool such as plugman could corrupt plugins. Prison was not designed to do soft reloads and as such mines, ranks, ladders, and even some player settings and histories could be corrupted. +
@@ -89,7 +106,7 @@ Reload EssentialsX settings, or restart the server. # Essentials Currency Commands -Eventually you may have to deal with currency, so here are the esstentals commands. +Eventually you may have to deal with currency, so here are the essentials commands. * `/eco` - Show the EssentialsX economy commands * `/eco give ` - Give a player money diff --git a/docs/prison_docs_0xx_setting_up_PlaceholderAPI.md b/docs/prison_docs_0xx_setting_up_PlaceholderAPI.md index 40222f51d..ede61fd89 100644 --- a/docs/prison_docs_0xx_setting_up_PlaceholderAPI.md +++ b/docs/prison_docs_0xx_setting_up_PlaceholderAPI.md @@ -40,6 +40,8 @@ Setting up PlaceholderAPI just need couple of steps: * Restart your server. Do not use **/reload** or you'll break Prison Placeholders. Prison registers all of the placeholders upon server startup so the registrations will be lost. +* NOTE: Prison now has placeholders reload feature, but the first time you install PlaceholderAPI you will have to restart the server for everything to be properly registered. +
@@ -52,9 +54,28 @@ Use the command **/prison placeholders** for a listing the placeholder commands. * **/prison placeholders search ** * **/prison placeholders test ** + +* **/prison placeholders reload** or **/prison reload placeholders** + - This will reload all placeholders and will re-register them with the proper placeholder plugins. Both of these commands are exactly the same. + + +Example of reloading prison's placeholders with stats on what was registered. + +Reloading Prison Placeholders + + + * **/prison version** + - The prison version command is useful for reviewing that placeholder plugins are correctly registered. + + +* **Prison startup logs** + - The Prison startup messages provides a detailed list of stats pertaining to placeholders, such as the break down of how many were registered and available. + + +Start up placeholder stats + -The listing of all the placeholders is available within the Prison startup information, and through `/prison version`.
@@ -76,9 +97,18 @@ The solution was to download from PlaceholderAPI, their modified version of Vaul /papi reload ``` -As a note, I'm not sure how well Prison behaves with the use of `/papi reload`. It may be good to test with, but safer to just restart the server, once everything appears to be working and looks good. The point is that any plugin reload is good to test with, but if you're going to let your server run for months, its probably best to do a clean restart. +If you use `/papi reload`/ then you will have to reload the placeholders in prison so they are registered with papi. When papi reloads, it forgets everything that was registered before. + + +You can use either one of the following commands to reload and re-register all of prison's placeholders. Both commands are exactly the same. + +``` +/prison placeholders reload +/prison reload placeholders +``` + +If you create new ranks or mines you will also have to reload the prison placeholders. You don't have to reload papi in these situations, just prison. -With this example of installing the PlaceholderAPI and downloading their version of Vault and Essentials, the player reported that once the economy placeholder was working, another placeholder stopped working. Their solution was to reinstall all of the papi (PlaceholderAPI) plugins (not sure if that includes reinstalling papi's version of Vault and Essentials) and then restarted the server. The point here, is a clean start is probably helpful.
diff --git a/docs/prison_docs_101_setting_up_mines.md b/docs/prison_docs_101_setting_up_mines.md index f1cddb4ef..dfb8755ac 100644 --- a/docs/prison_docs_101_setting_up_mines.md +++ b/docs/prison_docs_101_setting_up_mines.md @@ -24,7 +24,7 @@ Items to add to this document: # New! Prison Fast Start Prison now has a new set of features that can help you get up and running faster than ever! `/ranks autoConfigure`. It can auto create your ranks and virtual mines, A through Z, it will link the mines to the ranks, setup the basic rank commands to provide basic access permissions for your players, and assign blocks of increasing values to all mines. All you need to do is to use the command `/mines set area` on all mines to make them physical mines. Plus there are a new features to help provide the finishing touches in almost no time. - - `/ranks autoConfigure` + - `/ranks autoConfigure` - `/mines set area help` - `/mines set tracer help` - `/mines set size help` @@ -265,6 +265,26 @@ Note: The new command `/mines set move` is not yet enabled. It is still in devel
+# Large Mines - Preventing Lag + +Large mines present their special own special challenges, one of which is that they can take a long time to reset. Since bukkit cannot handle async resets of blocks because of world corruption, the updates must happen synchronously in the main server thread. For large mines, that can mean causing a significant amount of lag. + +To prevent lagging the server, Prison has a feature that can prevent any lag from happening while performing the reset. This feature is called **Reset Paging**. This feature doesn't have to be used with just large mines, but the reset process is a little more complex. When testing, it was actually found to be slightly faster than the normal reset method. + +To enable reset paging use the following commands to enable and disable it. + +``` +/mines set resetPaging enable +/mines set resetPaging disable +``` + +The way it works, is that it performs small pages of block updates and keeps an eye on how long it's taking. If the update goes beyond a set amount of time, such as 50 milliseconds, it stops the updates, and then schedules the remaining updates to run later, with no delay. That means if nothing else is trying to run within the main server thread, then it will continue to perform block updates. But if something else was waiting to run, then the mine update will pause and allow the other process to finish. This will prevent vital tasks from backing up because the mine reset yields to other tasks that need to run. + + + + +
+ # Next Steps - Skipping Resets, Notifications, and Zero Blocks diff --git a/docs/prison_docs_113_setting_up_sellall.md b/docs/prison_docs_113_setting_up_sellall.md index fc96ac1b6..97193130e 100644 --- a/docs/prison_docs_113_setting_up_sellall.md +++ b/docs/prison_docs_113_setting_up_sellall.md @@ -83,6 +83,42 @@ How Multipliers work -> they'll just multiply the value of what you sold, for ex so ```1000 * 1 = 1000``` is what you'll get (by default this's the value in the sellallconfig.yml), but if you've a Prestige with a multiplier of maybe ```1.5```, then you'll get ```1000 * 1.5 = 1500```, this isn't even hard math but could make you some confusion. +**SellaAll Signs:** + +Open your config.yml and turn on true the sellall sign like this: +``` +# NEW: SellAll sign +# New sellall feature which enable a sign with the name of [SellAll] to execute the command /sellall sell of Prison +# To make a sign, give yourself the permission prison.admin and then add as the first line of a sign the tag [SellAll] +sellall-sign: true +sellall-sign-notify: true +sellall-sign-visible-tag: "&7[&3SellAll&7]" +``` +You can also turn on or off a notification when clicking the sign, you can edit that in the module-conf/lang/en_US.yml file, and you can edit +the tag from the config.yml which's shown in the sign. + +To make a Sign, just place a sign and add as the first line ```[SellAll]```, also be sure to have the permissions ```prison.sign```. +If everything's right, the sign will look like the sellall-sign-visible-tag from the config.yml, and will work on right clicking it. + +**SellAll Auto** + +You can turn on or off from the SellAllConfig.yml file the SellAll Auto feature, which will sell everything sellable from the player inventory when it's full. +Just edit these config lines like this: +``` + Full_Inv_AutoSell: 'true' + Full_Inv_AutoSell_Notification: 'false' +``` +You can edit the autoSell notification as you want. + +It's also possible to enable or disable sellAll per-User, it'll be them to choose if enable it or not. +They'll need to use the command: `/sellall auto toggle`, it'll let them enable or disable it, when used +for the first time, the user will be stored in the `users` section of the `sellAllConfig.yml`. + +The admin can enable this feature from the `sellAllConfig.yml`, by changing this option from `false` to `true`: +``` + Options.Full_Inv_AutoSell_perUserToggleable: false +``` + # LIST OF COMMANDS ``` /sellall diff --git a/gradle.properties b/gradle.properties index e98ec377c..50012d982 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.2-alpha.14 +version=3.2.3 ## org.gradle.warning.mode=(all,none,summary) org.gradle.warning.mode=all diff --git a/knownissues_v3.2.x.md b/knownissues_v3.2.x.md index ee9ae611b..6b79f4e18 100644 --- a/knownissues_v3.2.x.md +++ b/knownissues_v3.2.x.md @@ -7,7 +7,77 @@ a short list of To Do's. This list is intended to help work through known issues, and/or to serve as items that should be added, or fixed. -# To Do Items - During Alpha v3.2.2 +# To Do Items - During Alpha v3.2.3 + + +- Placeholder Attributes: + A way for placeholders to be customized dynamically other plugin configs. + Example would be a scoreboard that uses bar graphs but customizes each one to different colors, characters, and size. + Use :: to identify the start of an attribute followed by the type of attribute. + Examples: ::nFormat: and ::bar: + Use of : to separate each parameter. + + + +- Hex colors: + https://www.spigotmc.org/threads/hex-color-code-translate.449748/#post-3867804 + https://regex101.com/ + (?i)&#[A-Fa-f0-9]{6}|&[0-9A-FK-OR] + + +- Possible issue with auto features preventing WorldGuard from protecting a + mine. In the auto features GUI, when the bottom three features are turned + off then WG won't protect the region. + + +- auto manager - durability not working even when feature is enabled +- autoConfigure - fixed? + + +- mines - add storage for liner so it can be regenerated +- mine liner - add bedrock +- BlockEvents - submit to run synch or async. +- BlockEvents - multiple on same command. Use ; as separators +- auto features - fixed - durabilty not working +- auto features - cannot turn off smelt or blocking +- auto features - issue with lore +- world guard - not working properly + + +* **Custom block issues** +- If CustomItems is loaded successfully but yet not using new block model, show error message +- Show a message at startup indicating that the new block model is enabled or not enabled + + +* **Rework rank permissions to eliminate need to put perms in rank commands** +- Enhance the PermissionIntegration abstract class to also work with group perms. +- Add to ranks two new fields: permissions and permissionGroups. Save and load. +- Add a new boolean field to ranks: usePermissions. Save and load. +- Add support for these perms within rank commands +- Rewrite rankups to use these perms when ranking up, promote, demote, and also for prestiges + + +* **Prestige Options** + - Reset money on prestige - boolean option + - Auto Prestige - server setting or player setting? + - prestigemax - keep applying prestiges until run out of funds + - rankmax - keep applying rankups until run out of funds + - Eliminate prestige ranks - (optional) + * Would need ladder commands + * Need to define an upper limit of how many + * tags may have a placeholder: `&7[&3P&a{p_level}&7]` + * Have a base cost of prestige: example 100,000,000 + * Have a cost multiplier for ranks: example: 10% more expensive each rank with each prestige + * Have a cost multiplier for prestiging: example: 20% more expensive each prestige + * Have a cost multiplier for /sellall: Example: 0.005% (1/2 increase in sale price) or -0.015% (1.5% decrease in sale price to make it even more difficult per prestige) + * Have a list of permissions and permission groups + * The above settings are pretty general and would apply to all generated prestige levels, but to allow for customizations, then ladder ranks, perms and perm groups could be setup to accept a level parameter to be applied at a specific level. Tags set at a given level could also be applied to higher levels until another tag takes it place. + + + +* **DONE: Sellall - Hook up to prison command handler** +Currently sellall is not hooked up to the prison command handler and it needs to be. + * **Get new block model working** @@ -84,7 +154,7 @@ Implement and have a fully functional new block handling mechanism that operate -* **DONE? Rework commands within the spigot module so all user facing commands are routed through Prison's Command Interface** +* **DONE! Rework commands within the spigot module so all user facing commands are routed through Prison's Command Interface** Blue should work on this. diff --git a/prison-core/src/main/java/tech/mcprison/prison/Prison.java b/prison-core/src/main/java/tech/mcprison/prison/Prison.java index 7287907b6..66b09988f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/Prison.java +++ b/prison-core/src/main/java/tech/mcprison/prison/Prison.java @@ -27,7 +27,7 @@ import tech.mcprison.prison.commands.CommandHandler; import tech.mcprison.prison.error.ErrorManager; import tech.mcprison.prison.integration.IntegrationManager; -import tech.mcprison.prison.internal.block.PrisonBlockTypes; +import tech.mcprison.prison.integration.PlaceholderManager; import tech.mcprison.prison.internal.platform.Platform; import tech.mcprison.prison.localization.LocaleManager; import tech.mcprison.prison.modules.Module; @@ -83,9 +83,12 @@ public class Prison private ErrorManager errorManager; private TroubleshootManager troubleshootManager; private IntegrationManager integrationManager; + + private PlaceholderManager placeholderManager; + private Database metaDatabase; - private PrisonBlockTypes prisonBlockTypes; + /** * Gets the current instance of this class.

An instance will always be available after @@ -135,15 +138,7 @@ public boolean init(Platform platform, String minecraftVersion) { this.commandHandler.registerCommands(prisonCommands); - // Setup hooks in to the valid prison block types. This will be only - // the block types that have tested to be valid on the server that is - // running prison. This provides full compatibility to the admins that - // if a block is listed, then it's usable. No more guessing or finding - // out after the fact that a block that was used was invalid for - // their version of minecraft. - this.prisonBlockTypes = new PrisonBlockTypes(); - this.prisonBlockTypes.loadServerBlockTypes(); - + long stopTime = System.currentTimeMillis(); @@ -217,6 +212,7 @@ private void initManagers() { this.selectionManager = new SelectionManager(); this.troubleshootManager = new TroubleshootManager(); this.integrationManager = new IntegrationManager(); + this.placeholderManager = new PlaceholderManager(); // try { @@ -375,16 +371,13 @@ public IntegrationManager getIntegrationManager() { return integrationManager; } + /** - * Setup hooks in to the valid prison block types. This will be only the - * block types that have tested to be valid on the server that is running - * prison. This provides full compatibility to the admins that if a block - * is listed, then it's usable. No more guessing or finding out after the - * fact that a block that was used was invalid for their version of minecraft. + * Returns the integration manager, which returns {@link tech.mcprison.prison.integration.Integration}s. */ - public PrisonBlockTypes getPrisonBlockTypes() { - return prisonBlockTypes; - } - + public PlaceholderManager getPlaceholderManager() { + return placeholderManager; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 117ea07e1..5237d147d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -673,6 +673,19 @@ public void autoFeaturesInformation(CommandSender sender) { } + @Command(identifier = "prison debug", + description = "For internal use only. Do not use until instructed since this is not hookedup.", + onlyPlayers = false ) + public void toggleDebug(CommandSender sender ) { + + Output.get().setDebug( !Output.get().isDebug() ); + + String message = "Debug logging: " + (Output.get().isDebug() ? "enabled" : "disabled"); + + sender.sendMessage( message ); + } + + // This functionality should not be available in v3.2.1! If someone is still running Prison 2.x.x // then they must first upgrade to diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index 67b8cd2a1..b23ffaf3c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -2,11 +2,13 @@ import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.autofeatures.ValueNode.NodeType; import tech.mcprison.prison.file.YamlFileIO; import tech.mcprison.prison.output.Output; @@ -17,7 +19,7 @@ public class AutoFeaturesFileConfig { // private FileConfiguration config; private Map config; - + public enum AutoFeatures { @@ -67,8 +69,12 @@ public enum AutoFeatures { autoPickup(options), autoPickupEnabled(autoPickup, true), + autoPickupLimitToMines(autoPickup, true), autoPickupAllBlocks(autoPickup, true), + autoPickupBlockNameList(autoPickup, NodeType.STRING_LIST, + "coal_block", "iron_ore"), + autoPickupCobbleStone(autoPickup, true), autoPickupStone(autoPickup, true), autoPickupGoldOre(autoPickup, true), @@ -85,6 +91,7 @@ public enum AutoFeatures { autoSmelt(options), autoSmeltEnabled(autoSmelt, true), + autoSmeltLimitToMines(autoSmelt, true), autoSmeltAllBlocks(autoSmelt, true), @@ -94,6 +101,7 @@ public enum AutoFeatures { autoBlock(options), autoBlockEnabled(autoBlock, true), + autoBlockLimitToMines(autoBlock, true), autoBlockAllBlocks(autoBlock, true), @@ -119,6 +127,7 @@ public enum AutoFeatures { private final boolean isInteger; private final boolean isLong; private final boolean isDouble; + private final boolean isStringList; private final String path; private final String message; @@ -126,6 +135,7 @@ public enum AutoFeatures { private final Integer intValue; private final Long longValue; private final Double doubleValue; + private final List listValue; private AutoFeatures() { this.parent = null; @@ -135,12 +145,15 @@ private AutoFeatures() { this.isInteger = false; this.isLong = false; this.isDouble = false; + this.isStringList = false; + this.path = null; this.message = null; this.value = null; this.intValue = null; this.longValue = null; this.doubleValue = null; + this.listValue = new ArrayList<>(); } private AutoFeatures(AutoFeatures section) { this.parent = section; @@ -150,12 +163,15 @@ private AutoFeatures(AutoFeatures section) { this.isInteger = false; this.isLong = false; this.isDouble = false; + this.isStringList = false; + this.path = section.getKey(); this.message = null; this.value = null; this.intValue = null; this.longValue = null; this.doubleValue = null; + this.listValue = new ArrayList<>(); } private AutoFeatures(AutoFeatures section, String message) { this.parent = section; @@ -165,12 +181,15 @@ private AutoFeatures(AutoFeatures section, String message) { this.isInteger = false; this.isLong = false; this.isDouble = false; + this.isStringList = false; + this.path = section.getKey(); this.message = message; this.value = null; this.intValue = null; this.longValue = null; this.doubleValue = null; + this.listValue = new ArrayList<>(); } private AutoFeatures(AutoFeatures section, Boolean value) { this.parent = section; @@ -180,12 +199,38 @@ private AutoFeatures(AutoFeatures section, Boolean value) { this.isInteger = false; this.isLong = false; this.isDouble = false; + this.isStringList = false; + this.path = section.getKey(); this.message = null; this.value = value == null ? Boolean.FALSE : value; this.intValue = null; this.longValue = null; this.doubleValue = null; + this.listValue = new ArrayList<>(); + } + private AutoFeatures(AutoFeatures section, NodeType nodeType, String... values ) { + this.parent = section; + this.isSection = false; + this.isBoolean = false; + this.isMessage = false; + this.isInteger = false; + this.isLong = false; + this.isDouble = false; + this.isStringList = (nodeType == NodeType.STRING_LIST); + + this.path = section.getKey(); + this.message = null; + this.value = null; + this.intValue = null; + this.longValue = null; + this.doubleValue = null; + this.listValue = new ArrayList<>(); + + if ( values != null && values.length > 0 ) { + + this.listValue.addAll( Arrays.asList( values )); + } } public AutoFeatures getParent() { @@ -209,6 +254,9 @@ public boolean isLong() { public boolean isDouble() { return isDouble; } + public boolean isStringList() { + return isStringList; + } public String getPath() { return path; @@ -229,6 +277,9 @@ public Long getLongValue() { public Double getDoubleValue() { return doubleValue; } + public List getListValue() { + return listValue; + } public String getKey() { return (path != null ? path + "." : "") + this.name(); @@ -304,8 +355,24 @@ else if ( getValue() != null ) { results = getValue().booleanValue(); } + return results; + } + + public List getStringList( Map conf ) { + List results = null; + + if ( conf.containsKey(getKey()) && conf.get( getKey() ).isStringListNode() ) { + StringListNode list = (StringListNode) conf.get( getKey() ); + results = list.getValue(); + } + else if ( getValue() != null ) { + results = new ArrayList<>(); + } + return results; } + + /** *

Get the children nodes to the given item. @@ -372,6 +439,11 @@ public AutoFeaturesFileConfig() { // key, value.toString() ); // } + List blockNames = getFeatureStringList( AutoFeatures.autoPickupBlockNameList ); + StringBuilder sbBlockName = new StringBuilder( String.join( ", ", blockNames ) ).insert( 0, "[" ).append( "]" ); + Output.get().logInfo( "###--### AutoFeaturesFileConfig: test autoPickupBlockNameList: length = %d value = %s ", + blockNames.size(), sbBlockName.toString() ); + } @@ -460,6 +532,11 @@ public String getFeatureMessage( AutoFeatures feature ) { return feature.getMessage( getConfig() ); } + public List getFeatureStringList( AutoFeatures feature ) { + + return feature.getStringList( getConfig() ); + } + public boolean saveConf() { return saveConf( getConfig() ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/StringListNode.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/StringListNode.java new file mode 100644 index 000000000..383aedcf8 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/StringListNode.java @@ -0,0 +1,73 @@ +package tech.mcprison.prison.autofeatures; + +import java.util.ArrayList; +import java.util.List; + +public class StringListNode + extends ValueNode +{ + private static final long serialVersionUID = -1L; + + + protected final List value; + + public StringListNode(List stringList) { + super(); + if ( stringList == null ) { + this.value = new ArrayList<>(); + } + else { + this.value = stringList; + } + } + + public static StringListNode valueOf(List stringList) + { + return new StringListNode( stringList ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append( String.join( ", ", getValue() ) ); + sb.insert( 0, "[" ).append("]"); + + return sb.toString(); + } + + public List getValue() { + return value; + } + + @Override + public boolean isStringListNode() { return true; } + + @Override + public NodeType getNodeType() { + return NodeType.STRING_LIST; + } + + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null) return false; + if (o instanceof StringListNode) { + + final List otherValue = ((StringListNode) o).getValue(); + if ( getValue() == null && otherValue == null ) return true; + if ( getValue() != null ) { + return getValue().equals( otherValue ); + } + } + return false; + } + + @Override + public int hashCode() { + // same as hashCode that List uses + return getValue().hashCode(); + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/ValueNode.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/ValueNode.java index 698787d0e..9a7757569 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/ValueNode.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/ValueNode.java @@ -17,7 +17,8 @@ public enum NodeType { BOOLEAN, LONG, INTEGER, - DOUBLE + DOUBLE, + STRING_LIST ; } @@ -33,6 +34,8 @@ public enum NodeType { public boolean isDoubleNode() { return false; } + public boolean isStringListNode() { return false; } + public abstract NodeType getNodeType(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java b/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java index ea69d4cc7..fcca7f5f8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java @@ -1,6 +1,7 @@ package tech.mcprison.prison.commands; import java.util.Optional; +import java.util.UUID; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; @@ -31,11 +32,18 @@ public void setCmdGroup( String cmdGroup ) { * the offline player list. If not one is found, then return a null. *

* + *

The getOfflinePlayer() will now include RankPlayer as a fall back to help + * ensure a player is always returned, if its a valid player. + *

+ * * @param sender * @param playerName is optional, if not supplied, then sender will be used * @return Player if found, or null. */ public Player getPlayer( CommandSender sender, String playerName ) { + return getPlayer( sender, playerName, null ); + } + public Player getPlayer( CommandSender sender, String playerName, UUID uuid ) { Player result = null; playerName = playerName != null ? playerName : sender != null ? sender.getName() : null; @@ -47,13 +55,18 @@ public Player getPlayer( CommandSender sender, String playerName ) { if ( !opt.isPresent() ) { opt = Prison.get().getPlatform().getOfflinePlayer( playerName ); } + if ( !opt.isPresent() ) { + opt = Prison.get().getPlatform().getOfflinePlayer( uuid ); + } if ( opt.isPresent() ) { result = opt.get(); } + } return result; } + public double getPlayerBalance( Player player ) { EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java index 8185b00a0..8b48e24fb 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java @@ -30,7 +30,11 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.commands.handlers.BlockArgumentHandler; import tech.mcprison.prison.commands.handlers.DoubleArgumentHandler; +import tech.mcprison.prison.commands.handlers.DoubleClassArgumentHandler; import tech.mcprison.prison.commands.handlers.IntegerArgumentHandler; +import tech.mcprison.prison.commands.handlers.IntegerClassArgumentandler; +import tech.mcprison.prison.commands.handlers.LongArgumentHandler; +import tech.mcprison.prison.commands.handlers.LongClassArgumentHandler; import tech.mcprison.prison.commands.handlers.PlayerArgumentHandler; import tech.mcprison.prison.commands.handlers.StringArgumentHandler; import tech.mcprison.prison.commands.handlers.WorldArgumentHandler; @@ -76,9 +80,15 @@ public CommandHandler() { this.tabCompleaterData = new TabCompleaterData(); - registerArgumentHandler(String.class, new StringArgumentHandler()); registerArgumentHandler(int.class, new IntegerArgumentHandler()); registerArgumentHandler(double.class, new DoubleArgumentHandler()); + registerArgumentHandler(long.class, new LongArgumentHandler()); + + registerArgumentHandler(Integer.class, new IntegerClassArgumentandler()); + registerArgumentHandler(Double.class, new DoubleClassArgumentHandler()); + registerArgumentHandler(Long.class, new LongClassArgumentHandler()); + + registerArgumentHandler(String.class, new StringArgumentHandler()); registerArgumentHandler(Player.class, new PlayerArgumentHandler()); registerArgumentHandler(World.class, new WorldArgumentHandler()); registerArgumentHandler(BlockType.class, new BlockArgumentHandler()); @@ -213,7 +223,7 @@ public String[] getHelpMessage(RegisteredCommand command) { String subCmd = scommand.getUsage(); int subCmdSubCnt = scommand.getSuffixes().size(); - String subCommands = (subCmdSubCnt <= 1 ? "" : + String subCommands = (subCmdSubCnt == 0 ? "" : ChatColor.DARK_AQUA + "(" + subCmdSubCnt + " Subcommands)"); String isAlias = scommand.isAlias() ? ChatColor.DARK_AQUA + " Alias" : ""; @@ -527,18 +537,20 @@ private RegisteredCommand commandRegisterConfig( Method method, Command commandA RegisteredCommand mainCommand = getRootCommands().get( rootPluginCommand ); for (int i = 1; i < identifiers.length; i++) { + String suffix = identifiers[i]; - if (mainCommand.doesSuffixCommandExist(suffix)) { + if ( mainCommand.doesSuffixCommandExist(suffix) ) { mainCommand = mainCommand.getSuffixCommand(suffix); - } else { + } + else { RegisteredCommand newCommand = new RegisteredCommand(suffix, this, mainCommand); - newCommand.setAlias( alias != null ); + newCommand.setAlias( alias != null ); mainCommand.addSuffixCommand(suffix, newCommand); - // Must add all new RegisteredCommand objects to both getAllRegisteredCommands() and - // getTabCompleterData(). - getAllRegisteredCommands().add( newCommand ); - getTabCompleaterData().add( newCommand ); + // Must add all new RegisteredCommand objects to both getAllRegisteredCommands() and + // getTabCompleterData(). + getAllRegisteredCommands().add( newCommand ); + getTabCompleaterData().add( newCommand ); mainCommand = newCommand; } @@ -593,7 +605,19 @@ public boolean onCommand(CommandSender sender, PluginCommand command, String lab else { - rootCommand.execute(sender, args); + try { + rootCommand.execute(sender, args); + } + catch ( Exception e ) { + String message = "Prison CommandHander: onCommand: " + e.getMessage() + + " [" + e.getCause() == null ? "cause not reported" : e.getCause() + "]"; + + Output.get().logError( message ); + for ( StackTraceElement ste : e.getStackTrace() ) { + Output.get().logError( ste.toString() ); + } + + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java index 9a759176b..f81a536e6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java @@ -14,6 +14,7 @@ public class CommandPagedData { private int curPage = 1; private boolean showAll = false; + private boolean debug = false; private int pageSize = MAX_PAGE_SIZE; private int pages = 1; @@ -40,8 +41,12 @@ public CommandPagedData( String pageCommand, int itemSize, int extraPages, Strin this.pageCommand = pageCommand; - if ( "all".equalsIgnoreCase( page )) { - this.showAll = true; + if ( "all".equalsIgnoreCase( page ) ) { + setShowAll( true );; + } + else if ( "debug".equalsIgnoreCase( page ) ) { + setShowAll( true );; + setDebug( true ); } this.curPage = 1; @@ -140,6 +145,13 @@ public void setShowAll( boolean showAll ) { this.showAll = showAll; } + public boolean isDebug() { + return debug; + } + public void setDebug( boolean debug ) { + this.debug = debug; + } + public int getPageSize() { return pageSize; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java index 524f13d30..a27ce2b29 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java @@ -322,7 +322,7 @@ private Object getMethodInstance() { } public RegisteredCommand getSuffixCommand(String suffix) { - return suffixesByName.get(suffix); + return suffixesByName.get(suffix.toLowerCase()); } public List getSuffixes() { diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java index 1af2272cd..5728a17f1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java @@ -28,11 +28,14 @@ public class DoubleArgumentHandler extends NumberArgumentHandler { public DoubleArgumentHandler() { } - @Override public Double transform(CommandSender sender, CommandArgument argument, String value) + @Override + public Double transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - value = value.replace("$", ""); - value = value.replace("%", ""); + value = value.replaceAll( "$|%", "" ); try { +// if ( value == null || value.trim().length() == 0 ) { +// return null; +// } return Double.parseDouble(value); } catch (NumberFormatException e) { throw new TransformError( diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java new file mode 100644 index 000000000..2842f043a --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java @@ -0,0 +1,34 @@ +package tech.mcprison.prison.commands.handlers; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.CommandArgument; +import tech.mcprison.prison.commands.TransformError; +import tech.mcprison.prison.internal.CommandSender; + +public class DoubleClassArgumentHandler extends NumberArgumentHandler { + + public DoubleClassArgumentHandler() { + } + + @Override + public Double transform(CommandSender sender, CommandArgument argument, String value) + throws TransformError { + Double results = null; + + if ( value != null ) { + + value = value.replaceAll( "$|%", "" ); + if ( value.trim().length() > 0 ) { + try { + results = Double.parseDouble(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + } + return results; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java index bbae89071..dc5710bca 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java @@ -23,12 +23,14 @@ import tech.mcprison.prison.commands.TransformError; import tech.mcprison.prison.internal.CommandSender; -public class IntegerArgumentHandler extends NumberArgumentHandler { +public class IntegerArgumentHandler + extends NumberArgumentHandler { public IntegerArgumentHandler() { } - @Override public Integer transform(CommandSender sender, CommandArgument argument, String value) + @Override + public Integer transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { try { return Integer.parseInt(value); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java new file mode 100644 index 000000000..f2848b147 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java @@ -0,0 +1,34 @@ +package tech.mcprison.prison.commands.handlers; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.CommandArgument; +import tech.mcprison.prison.commands.TransformError; +import tech.mcprison.prison.internal.CommandSender; + +public class IntegerClassArgumentandler + extends NumberArgumentHandler { + + + public IntegerClassArgumentandler() { + } + + @Override public Integer transform(CommandSender sender, CommandArgument argument, String value) + throws TransformError { + Integer results = null; + + if ( value != null ) { + + //value = value.replaceAll("$|%", ""); + if ( value.trim().length() > 0 ) { + try { + results = Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + } + return results; + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java new file mode 100644 index 000000000..f31b05f95 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java @@ -0,0 +1,26 @@ +package tech.mcprison.prison.commands.handlers; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.CommandArgument; +import tech.mcprison.prison.commands.TransformError; +import tech.mcprison.prison.internal.CommandSender; + +public class LongArgumentHandler + extends NumberArgumentHandler { + + public LongArgumentHandler() { + } + + @Override + public Long transform(CommandSender sender, CommandArgument argument, String value) + throws TransformError { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java new file mode 100644 index 000000000..31469f88d --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java @@ -0,0 +1,33 @@ +package tech.mcprison.prison.commands.handlers; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.CommandArgument; +import tech.mcprison.prison.commands.TransformError; +import tech.mcprison.prison.internal.CommandSender; + +public class LongClassArgumentHandler + extends NumberArgumentHandler { + + public LongClassArgumentHandler() { + } + + @Override + public Long transform(CommandSender sender, CommandArgument argument, String value) + throws TransformError { + Long results = null; + + if ( value != null ) { + try { + results = Long.parseLong(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + + return results; + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java index a916c4079..75071c04f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java @@ -2,9 +2,12 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; +import java.util.List; import tech.mcprison.prison.error.Error; import tech.mcprison.prison.error.ErrorManager; @@ -46,7 +49,14 @@ protected void saveFile( File file, String data ) try { // Write as a .tmp file: - Files.write( tempFile.toPath(), data.getBytes() ); + + // Add json data to lines, splitting on \n: + List lines = Arrays.asList( data.split( "\n" )); + + // Write as an UTF-8 stream: + Files.write( tempFile.toPath(), lines, StandardCharsets.UTF_8 ); + +// Files.write( tempFile.toPath(), data.getBytes() ); // If original target exists, then delete it: if ( file.exists() ) @@ -66,19 +76,26 @@ protected void saveFile( File file, String data ) protected String readFile( File file ) { - String results = null; + StringBuilder results = new StringBuilder(); +// String results = null; try { - byte[] bytes = Files.readAllBytes( file.toPath() ); - results = new String(bytes); + List lines = Files.readAllLines( file.toPath(), StandardCharsets.UTF_8 ); + + for ( String line : lines ) { + results.append( line ).append( "\n" ); + } + +// byte[] bytes = Files.readAllBytes( file.toPath() ); +// results = new String(bytes); } catch ( IOException e ) { logException( "Failed to load file", file, e ); } - return results; + return results.toString(); } private void logException( String description, File file, IOException e ) diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java index d7f34a259..04482a331 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.error.ErrorManager; import tech.mcprison.prison.modules.ModuleStatus; +import tech.mcprison.prison.output.Output; public class JsonFileIO extends FileIO @@ -65,7 +66,22 @@ public FileIOData readJsonFile( File file, FileIOData data ) if ( json != null ) { - results = getGson().fromJson( json, data.getClass() ); + try + { + results = getGson().fromJson( json, data.getClass() ); + } + catch ( Exception e ) { + + String message = String.format( + "JsonFileIO.readJsonFile: JsonParse failure: file: [%s] " + + "error: [%s] json: [%s] ", + file.getAbsoluteFile(), e.getMessage(), + json ); + + Output.get().logError( message ); + + // e.printStackTrace(); + } } return results; diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java index 67bec94af..022d741fc 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java @@ -12,6 +12,7 @@ import tech.mcprison.prison.autofeatures.DoubleNode; import tech.mcprison.prison.autofeatures.IntegerNode; import tech.mcprison.prison.autofeatures.LongNode; +import tech.mcprison.prison.autofeatures.StringListNode; import tech.mcprison.prison.autofeatures.TextNode; import tech.mcprison.prison.autofeatures.ValueNode; import tech.mcprison.prison.output.Output; @@ -64,7 +65,10 @@ else if ( value.isLongNode() ) { else if ( value.isIntegerNode() ) { set( key, ((IntegerNode) value).getValue() ); } - else { + else if ( value.isStringListNode() ) { + set( key, ((StringListNode) value).getValue() ); + } + else { // invalid type... not supported. // set( key, value ); } @@ -105,46 +109,57 @@ public List loadYamlAutoFeatures( Map config ) } for ( AutoFeatures autoFeat : AutoFeatures.values() ) { - ValueNode value = null; - String key = autoFeat.getKey(); + if ( autoFeat != null ) { + + ValueNode value = null; + String key = autoFeat.getKey(); + + if ( autoFeat.isSection() ) { + createSection( key ); + } + else if ( autoFeat.isBoolean() ) { + boolean boolVal = !yaml.containsKey( key ) ? autoFeat.getValue().booleanValue() : + Boolean.parseBoolean( yaml.get( key ).toString() ); + value = BooleanNode.valueOf( boolVal ); + } + else if ( autoFeat.isMessage() ) { + String text = !yaml.containsKey( key ) ? autoFeat.getMessage() : + yaml.get( key ).toString(); + value = TextNode.valueOf( text ); + } + else if ( autoFeat.isInteger() ) { + int intVal = !yaml.containsKey( key ) ? autoFeat.getIntValue().intValue() : + (int) yaml.get( key ); + value = IntegerNode.valueOf( intVal); + } + else if ( autoFeat.isLong() ) { + long longVal = !yaml.containsKey( key ) ? autoFeat.getLongValue().longValue() : + (long) yaml.get( key ); + value = LongNode.valueOf( longVal ); + } + else if ( autoFeat.isDouble() ) { + double doubVal = !yaml.containsKey( key ) ? autoFeat.getDoubleValue().doubleValue() : + (double) yaml.get( key ); + value = DoubleNode.valueOf( doubVal ); + } + else if ( autoFeat.isStringList() ) { - if ( autoFeat.isSection() ) { - createSection( key ); - } - else if ( autoFeat.isBoolean() ) { - boolean boolVal = !yaml.containsKey( key ) ? autoFeat.getValue().booleanValue() : - Boolean.parseBoolean( yaml.get( key ).toString() ); - value = BooleanNode.valueOf( boolVal ); - } - else if ( autoFeat.isMessage() ) { - String text = !yaml.containsKey( key ) ? autoFeat.getMessage() : - yaml.get( key ).toString(); - value = TextNode.valueOf( text ); - } - else if ( autoFeat.isInteger() ) { - int intVal = !yaml.containsKey( key ) ? autoFeat.getIntValue().intValue() : - (int) yaml.get( key ); - value = IntegerNode.valueOf( intVal); - } - else if ( autoFeat.isLong() ) { - long longVal = !yaml.containsKey( key ) ? autoFeat.getLongValue().longValue() : - (long) yaml.get( key ); - value = LongNode.valueOf( longVal ); - } - else if ( autoFeat.isDouble() ) { - double doubVal = !yaml.containsKey( key ) ? autoFeat.getDoubleValue().doubleValue() : - (double) yaml.get( key ); - value = DoubleNode.valueOf( doubVal ); - } - - - if ( !keys.contains( autoFeat.getKey() )) { - // AutoFeature does not exist in save file: - dne.add( autoFeat ); - } - - if ( value != null ) { - config.put( autoFeat.getKey(), value ); + @SuppressWarnings( "unchecked" ) + List stringListVal = !yaml.containsKey( key ) ? autoFeat.getListValue() : + (List) yaml.get( key ); + + value = StringListNode.valueOf( stringListVal ); + } + + + if ( !keys.contains( autoFeat.getKey() )) { + // AutoFeature does not exist in save file: + dne.add( autoFeat ); + } + + if ( value != null ) { + config.put( autoFeat.getKey(), value ); + } } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java new file mode 100644 index 000000000..591c13599 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java @@ -0,0 +1,60 @@ +package tech.mcprison.prison.integration; + +import java.util.List; + +import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; + +public abstract class CustomBlockIntegration + extends IntegrationCore { + + private PrisonBlockType blockType; + + private String blockPrefix; + + public CustomBlockIntegration( String keyName, String providerName, + PrisonBlockType blockType, String blockPrefix ) { + super( keyName, providerName, IntegrationType.CUSTOMBLOCK ); + + this.blockType = blockType; + this.blockPrefix = blockPrefix; + } + + public abstract String getCustomBlockId( Block block ); + + /** + *

This function is supposed to identify if the given block is a custom block, and + * if it is a custom block, then this function will return the correct PrisonBlock + * to match it's type. The PrisonBlock that will be returned, will come from the + * collection of valid blocks that were generated upon server startup. + *

+ * + *

If there is no match, then this function will return a null. + *

+ * + *

It's also important to know that the original block that is retrieved from + * PrisonBlockTypes.getBlockTypesByName() is cloned prior to returning it to this + * function, so it's safe to do anything you want with it. + *

+ * + * @param block + * @return The matched and cloned PrisonBlock, otherwise it will return a null if no match. + */ + public abstract PrisonBlock getCustomBlock( Block block ); + + public abstract Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ); + + + public abstract List getCustomBlockList(); + + + public PrisonBlockType getBlockType() { + return blockType; + } + + public String getBlockPrefix() { + return blockPrefix; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/Integration.java b/prison-core/src/main/java/tech/mcprison/prison/integration/Integration.java index 0cc4ac337..06c4bbf7c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/Integration.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/Integration.java @@ -121,6 +121,10 @@ public interface Integration { public String getPluginSourceURL(); + public String getVersion(); + public void setVersion( String version ); + + public String getDebugInfo(); public void setDebugInfo( String debugInfo ); public void addDebugInfo( String debugInfo ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationCore.java b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationCore.java index 236385f82..07516dac4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationCore.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationCore.java @@ -17,6 +17,8 @@ public class IntegrationCore private final IntegrationType type; private boolean registered = false; + private String version; + private String debugInfo; public IntegrationCore( String keyName, String providerName, IntegrationType type ) { @@ -103,8 +105,16 @@ public String getPluginSourceURL() { return null; } - @Override + public String getVersion() { + return version; + } + @Override + public void setVersion( String version ) { + this.version = version; + } + + @Override public String getDebugInfo() { return debugInfo; } @@ -117,5 +127,5 @@ public void addDebugInfo( String debugInfo ) { this.debugInfo = (this.debugInfo == null ? "" : this.debugInfo) + "(" + debugInfo + ")"; } - + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java index c55951826..da47dbfe7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java @@ -8,11 +8,11 @@ import java.util.Optional; import java.util.Set; -import tech.mcprison.prison.Prison; import tech.mcprison.prison.chat.FancyMessage; +import tech.mcprison.prison.integration.PlaceholderManager.PrisonPlaceHolders; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.output.DisplayComponent; import tech.mcprison.prison.output.FancyMessageComponent; -import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.TextComponent; /** @@ -33,495 +33,7 @@ public IntegrationManager() { this.deferredIntegrations = new ArrayList<>(); } - public static final String PRISON_PLACEHOLDER_PREFIX = "prison"; - public static final String PRISON_PLACEHOLDER_PREFIX_EXTENDED = PRISON_PLACEHOLDER_PREFIX + "_"; - - public static final String PRISON_PLACEHOLDER_MINENAME_SUFFIX = "_minename"; - public static final String PRISON_PLACEHOLDER_LADDERNAME_SUFFIX = "_laddername"; - - private PlaceholderProgressBarConfig progressBarConfig; - - public enum PlaceHolderFlags { - - PLAYER, - LADDERS, - MINES, - PLAYERMINES, - - SUPRESS, - ALIAS - ; - } - - /** - *

The given place holders should have both the prison prefix and without, - * with the without having the suppress value set. The suppressable items - * will not always be displayed since it would be implied that the prefix - * would have been provided. - *

- * - *

Update: The placeholders without the prison prefix have been eliminated - * since the prefix is now prepended when it is missing prior to matching to a - * valid placeholder enum. This cuts the number of generated placeholders in half. - * This is significant since with the addition of the aliases there would be about - * 744 placeholders generated if the prison had 30 mines setup! Now a 30 mine prison - * would have about 372. - *

- * - *

Note: In order to use these placeholders with something like holographic display - * you need to also include the placeholderAPI, - * plugin holographic extension and protocolib. - *

- * - *

In order to get the holographics extension to work it is critical you read - * their spigot page since you have to specify a refresh speed. - *

- * - * /hd addline temp2 Mine Size: {slowest}{prison_mines_blocks_size_temp2} - * or - * /hd addline temp2 Mine Size: {slowest}{prison_mines_blocks_size_temp2} - * /hd addline temp2 Mine Size: {slowest}%prison_mines_blocks_size_temp2% - * - * - * https://dev.bukkit.org/projects/holographic-displays - * https://www.spigotmc.org/resources/placeholderapi.6245/ - * https://www.spigotmc.org/resources/protocollib.1997/ - * https://www.spigotmc.org/resources/holographicextension.18461/ - */ - public enum PrisonPlaceHolders { - - no_match__(PlaceHolderFlags.SUPRESS), - - // Rank aliases: - prison_r(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rt(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rc(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rcf(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rcp(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rcb(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rcr(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rcrf(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rr(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_rrt(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - - - prison_rank(prison_r, PlaceHolderFlags.PLAYER), - prison_rank_tag(prison_rt, PlaceHolderFlags.PLAYER), - prison_rankup_cost(prison_rc, PlaceHolderFlags.PLAYER), - prison_rankup_cost_formatted(prison_rcf, PlaceHolderFlags.PLAYER), - prison_rankup_cost_percent(prison_rcp, PlaceHolderFlags.PLAYER), - prison_rankup_cost_bar(prison_rcb, PlaceHolderFlags.PLAYER), - prison_rankup_cost_remaining(prison_rcr, PlaceHolderFlags.PLAYER), - prison_rankup_cost_remaining_formatted(prison_rcrf, PlaceHolderFlags.PLAYER), - prison_rankup_rank(prison_rr, PlaceHolderFlags.PLAYER), - prison_rankup_rank_tag(prison_rrt, PlaceHolderFlags.PLAYER), - - - // Ladder aliases: - prison_r_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rt_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rc_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rcf_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rcp_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rcb_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rcr_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rcrf_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rr_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - prison_rrt_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), - - - prison_rank_laddername(prison_r_laddername, PlaceHolderFlags.LADDERS), - prison_rank_tag_laddername(prison_rt_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_laddername(prison_rc_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_formatted_laddername(prison_rcf_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_percent_laddername(prison_rcp_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_bar_laddername(prison_rcb_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_remaining_laddername(prison_rcr_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_cost_remaining_formatted_laddername(prison_rcrf_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_rank_laddername(prison_rr_laddername, PlaceHolderFlags.LADDERS), - prison_rankup_rank_tag_laddername(prison_rrt_laddername, PlaceHolderFlags.LADDERS), - - - - // player - prison_pb(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), - prison_player_balance(prison_pb, PlaceHolderFlags.PLAYER), - - prison_pb_laddername(prison_pb, PlaceHolderFlags.LADDERS), - prison_player_balance_laddername(prison_pb_laddername, PlaceHolderFlags.LADDERS), - - - - // Mine aliases: - prison_mn_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mt_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mi_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mif_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mtl_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mtlb_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mtlf_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_ms_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mr_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mrb_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mp_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mpc_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mbm_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - prison_mrc_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), - - - // reset_interval, reset_timeleft, blocks_size, blocks_remaining, blocks_percent - // player_count - // NOTE: Remove PrisonPlaceHolderFlags.SUPRESS when ready to be used: - prison_mines_name_minename(prison_mn_minename, PlaceHolderFlags.MINES), - prison_mines_tag_minename(prison_mt_minename, PlaceHolderFlags.MINES), - prison_mines_interval_minename(prison_mi_minename, PlaceHolderFlags.MINES), - prison_mines_interval_formatted_minename(prison_mif_minename, PlaceHolderFlags.MINES), - prison_mines_timeleft_minename(prison_mtl_minename, PlaceHolderFlags.MINES), - prison_mines_timeleft_bar_minename(prison_mtlb_minename, PlaceHolderFlags.MINES), - prison_mines_timeleft_formatted_minename(prison_mtlf_minename, PlaceHolderFlags.MINES), - prison_mines_size_minename(prison_ms_minename, PlaceHolderFlags.MINES), - prison_mines_remaining_minename(prison_mr_minename, PlaceHolderFlags.MINES), - prison_mines_remaining_bar_minename(prison_mrb_minename, PlaceHolderFlags.MINES), - prison_mines_percent_minename(prison_mp_minename, PlaceHolderFlags.MINES), - prison_mines_player_count_minename(prison_mpc_minename, PlaceHolderFlags.MINES), - prison_mines_blocks_mined_minename(prison_mbm_minename, PlaceHolderFlags.MINES), - prison_mines_reset_count_minename(prison_mrc_minename, PlaceHolderFlags.MINES), - - - - // PlayerMine aliases: - prison_mn_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mt_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mi_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mif_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mtl_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mtlb_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mtlf_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_ms_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mr_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mrb_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mp_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mpc_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mbm_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - prison_mrc_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), - - - prison_mines_name_playermines(prison_mn_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_tag_playermines(prison_mt_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_interval_playermines(prison_mi_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_interval_formatted_playermines(prison_mif_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_timeleft_playermines(prison_mtl_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_timeleft_bar_playermines(prison_mtlb_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_timeleft_formatted_playermines(prison_mtlf_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_size_playermines(prison_ms_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_remaining_playermines(prison_mr_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_remaining_bar_playermines(prison_mrb_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_percent_playermines(prison_mp_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_player_count_playermines(prison_mpc_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_blocks_mined_playermines(prison_mbm_pm, PlaceHolderFlags.PLAYERMINES), - prison_mines_reset_count_playermines(prison_mrc_pm, PlaceHolderFlags.PLAYERMINES), - - - - ; - - - private final PrisonPlaceHolders alias; - private final List flags; - private PrisonPlaceHolders() { - this.flags = new ArrayList<>(); - this.alias = null; - } - private PrisonPlaceHolders(PlaceHolderFlags... flags) { - this.alias = null; - this.flags = getFlags(flags); - } - private PrisonPlaceHolders(PrisonPlaceHolders alias, PlaceHolderFlags... flags) { - this.alias = alias; - this.flags = getFlags(flags); - } - - private List getFlags( PlaceHolderFlags[] flags ) { - List flagz = new ArrayList<>(); - if ( flags != null ) { - for ( PlaceHolderFlags flag : flags ) { - flagz.add( flag ); - } - } - return flagz; - } - - public PrisonPlaceHolders getAlias() - { - return alias; - } - - public boolean hasAlias() { - return alias != null; - } - public boolean isAlias() { - return flags.contains( PlaceHolderFlags.ALIAS ); - } - public boolean isSuppressed() { - return flags.contains( PlaceHolderFlags.SUPRESS ); - } - public boolean hasFlag( PlaceHolderFlags flag ) { - return flags.contains( flag ); - } - public List getFlags() { - return flags; - } - - public static PrisonPlaceHolders fromString( String placeHolder ) { - PrisonPlaceHolders result = no_match__; - - if ( placeHolder != null && placeHolder.trim().length() > 0 ) { - placeHolder = placeHolder.trim(); - - // This allows us to get rid of suppressed placeholders that were used for - // internal matching when placeholder APIs strip off the prefix: - if ( !placeHolder.toLowerCase().startsWith( PRISON_PLACEHOLDER_PREFIX ) ) { - placeHolder = PRISON_PLACEHOLDER_PREFIX + "_" + placeHolder; - } - - for ( PrisonPlaceHolders ph : values() ) { - if ( ph.name().equalsIgnoreCase( placeHolder ) ) { - result = ph; - break; - } - } - } - - return result; - } - - public static List getTypes(PlaceHolderFlags flag) { - List results = new ArrayList<>(); - - if ( flag != null ) { - for ( PrisonPlaceHolders ph : values() ) { - if ( ph.getFlags().contains( flag )) { - results.add( ph ); - } - } - } - - return results; - } - - public static List excludeTypes( - List list, PlaceHolderFlags flag) { - List results = new ArrayList<>(); - - if ( flag != null ) { - for ( PrisonPlaceHolders ph : list ) { - if ( !ph.getFlags().contains( flag )) { - results.add( ph ); - } - } - } - - return results; - } - - public String getChatText() { - return "&a" + name() + - (hasAlias() ? "&7(&b" + getAlias().name() + "&7)" : "") + - (isSuppressed() ? "&4*&a ": " "); - } - - public static String getAllChatTexts() { - return getAllChatTexts(false); - } - - public static String getAllChatTextsOmitSuppressable() { - return getAllChatTexts(true); - } - - private static List getAllChatList( boolean omitSuppressable) { - List results = new ArrayList<>(); - - boolean hasDeprecated = false; - - for ( PrisonPlaceHolders ph : values() ) - { - if ( !omitSuppressable || omitSuppressable && !ph.isSuppressed() && !ph.isAlias() ) { - if ( !hasDeprecated && ph.isSuppressed() ) { - hasDeprecated = true; - } - - results.add( ph.getChatText() ); - } - } - - if ( hasDeprecated ) { - results.add( " &2(&4*&2=&4suppressed&2)" ); - } - - return results; - } - - private static String getAllChatTexts( boolean omitSuppressable) { - StringBuilder sb = new StringBuilder(); - - List placeholders = getAllChatList(omitSuppressable); - - for ( String placeholder : placeholders ) { - sb.append( placeholder ); - } - - return sb.toString(); - } - - } - - - public void reloadPlaceholderBarConfig() { - setProgressBarConfig( loadPlaceholderBarConfig() ); - } - - public PlaceholderProgressBarConfig loadPlaceholderBarConfig() { - PlaceholderProgressBarConfig config = null; - - String barSegmentsStr = Prison.get().getPlatform().getConfigString( - "placeholder.bar-segments" ); - String barPositiveColor = Prison.get().getPlatform().getConfigString( - "placeholder.bar-positive-color" ); - String barPositiveSegment = Prison.get().getPlatform().getConfigString( - "placeholder.bar-positive-segment" ); - String barNegativeColor = Prison.get().getPlatform().getConfigString( - "placeholder.bar-negative-color" ); - String barNegativeSegment = Prison.get().getPlatform().getConfigString( - "placeholder.bar-negative-segment" ); - - - // All 5 must not be null: - if ( barSegmentsStr != null && barPositiveColor != null && barPositiveSegment != null && - barNegativeColor != null && barNegativeSegment != null ) { - - int barSegments = 20; - - try { - barSegments = Integer.parseInt( barSegmentsStr ); - } - catch ( NumberFormatException e ) { - Output.get().logWarn( - "IntegrationManager.loadPlaceholderBarConfigs(): Failure to convert the" + - "/plugins/Prison/config.yml prison-placeholder-configs.progress-bar.bar-segments " + - "to a valid integer. Defaulting to a value of 20 " + - "[" + barSegmentsStr + "] " + e.getMessage() ); - - } - - config = new PlaceholderProgressBarConfig( barSegments, - barPositiveColor, barPositiveSegment, - barNegativeColor, barNegativeSegment ); - } - - if ( config == null ) { - // go with default values because the config.yml is not up to date with - // the default values - - config = new PlaceholderProgressBarConfig( - 20, "&2", "#", "&4", "=" -// 20, "&2", "▊", "&4", "▒" - ); - - Output.get().logInfo( "The /plugins/Prison/config.yml does not contain the " + - "default values for the Placeholder Progress Bar." ); - Output.get().logInfo( "Default values are " + - "being used. To customize the bar, rename the config.yml and it will be " + - "regenerated and then edit to restore prior values."); - - } - - return config; - } - - public PlaceholderProgressBarConfig getProgressBarConfig() { - if ( progressBarConfig == null ) { - progressBarConfig = loadPlaceholderBarConfig(); - } - return progressBarConfig; - } - public void setProgressBarConfig( PlaceholderProgressBarConfig progressBarConfig ) { - this.progressBarConfig = progressBarConfig; - } - /** - *

This function uses the settings within the config.yml to construct a progress - * bar. It takes two numeric values and constructs it upon those parameters. - * The parameter

value
is the value that changes, and is the value that - * sets where the bar changes. The parameter
valueTotal
is the max value - * of where the
value
is increasing to. - *

- * - *

The lowest range is always zero and

value
will be set to zero if - * it is negative. If
value
is greater than
valueTotal
- * then it will be set to that value. The valid range for this function is only 0 percent - * to 100 percent. - *

- * - *

If the progress bar is moving in the wrong direction, then set the parameter - *

reverse
to true and then the
value
will be inverted by subtracting - * its value from
valueTotal
. - *

- * - * @param value A value that is changing. Will be set to zero if negative. Will be - * set to valueTotal if greater than that amount. - * @param valueTotal The target value that is non-changing. - * @param reverse Changes the growth direction of the progress bar. - * @return - */ - public String getProgressBar( double value, double valueTotal, boolean reverse ) { - StringBuilder sb = new StringBuilder(); - - // value cannot be greater than valueTotal: - if ( value > valueTotal ) { - value = valueTotal; - } - else if ( value < 0 ) { - value = 0; - } - - // If reverse, then the new value is subtracted from valueTotal: - if ( reverse ) { - value = valueTotal - value; - } - - double percent = value / valueTotal * 100.0; - - PlaceholderProgressBarConfig barConfig = - Prison.get().getIntegrationManager().getProgressBarConfig(); - - String lastColorCode = null; - for ( int i = 0; i < barConfig.getSegments(); i++ ) { - double pct = i / ((double)barConfig.getSegments()) * 100.0; - - if ( pct < percent ) { - if ( lastColorCode == null || - !barConfig.getPositiveColor().equalsIgnoreCase( lastColorCode )) { - sb.append( barConfig.getPositiveColor() ); - lastColorCode = barConfig.getPositiveColor(); - } - sb.append( barConfig.getPositiveSegment() ); - } - else { - if ( lastColorCode == null || - !barConfig.getNegativeColor().equalsIgnoreCase( lastColorCode )) { - sb.append( barConfig.getNegativeColor() ); - lastColorCode = barConfig.getNegativeColor(); - } - sb.append( barConfig.getNegativeSegment() ); - - } - } - - - return sb.toString(); - } - - /** * Returns a list of all of the {@link Integration}s that are registered under a certain {@link IntegrationType}, if any. * This includes integrations that have not successfully integrated. @@ -598,6 +110,35 @@ public EconomyCurrencyIntegration getEconomyForCurrency(String currency) { return results; } + + + public CustomBlockIntegration getCustomBlockIntegration( PrisonBlockType blockType ) + { + CustomBlockIntegration results = null; + + if(integrations.containsKey(IntegrationType.CUSTOMBLOCK)) { + + List cbIntegrations = getAllForType(IntegrationType.CUSTOMBLOCK); + + for ( Integration cbIntegration : cbIntegrations ) { + if ( cbIntegration.hasIntegrated() && cbIntegration instanceof CustomBlockIntegration ) { + + CustomBlockIntegration customBlock = (CustomBlockIntegration) cbIntegration; + + if ( customBlock.getBlockType() == blockType ) { + results = customBlock; + break; + } + } + } + + } + return results; + + } + + + public String getIntegrationDetails( IntegrationType integrationType ) { StringBuilder sb = new StringBuilder(); Set keys = integrations.keySet(); @@ -714,33 +255,39 @@ else if ( plugins == null || plugins.size() == 0 ) { return results; } + /** + * This adds the list of placeholders to the results List. + * @param results + */ public void getPlaceholderTemplateList( List results ) { results.add( new TextComponent( " &7Available PlaceHolders: " )); List placeholders = PrisonPlaceHolders.getAllChatList(true); - StringBuilder sb = new StringBuilder(); +// StringBuilder sb = new StringBuilder(); for ( String placeholder : placeholders ) { - if ( sb.length() == 0) { - sb.append( " " ); - sb.append( placeholder ); - } - else if ( (sb.length() + placeholder.length()) > 90) { - // will be too long combined so write existing sb then start over: - results.add( new TextComponent( sb.toString() )); - sb.setLength( 0 ); - - sb.append( " " ); - sb.append( placeholder ); - } else { - sb.append( placeholder ); - results.add( new TextComponent( sb.toString() )); - sb.setLength( 0 ); - } - } - if ( sb.length() > 0 ) { - results.add( new TextComponent( sb.toString() )); + results.add( new TextComponent( " " + placeholder )); + +// if ( sb.length() == 0) { +// sb.append( " " ); +// sb.append( placeholder ); +// } +// else if ( (sb.length() + placeholder.length()) > 90) { +// // will be too long combined so write existing sb then start over: +// results.add( new TextComponent( sb.toString() )); +// sb.setLength( 0 ); +// +// sb.append( " " ); +// sb.append( placeholder ); +// } else { +// sb.append( placeholder ); +// results.add( new TextComponent( sb.toString() )); +// sb.setLength( 0 ); +// } } +// if ( sb.length() > 0 ) { +// results.add( new TextComponent( sb.toString() )); +// } } public List getDeferredIntegrations() { @@ -754,4 +301,15 @@ public void addDeferredInitialization( Integration defferedIntegration ) { getDeferredIntegrations().add( defferedIntegration ); } + public void register( Integration integration, boolean isRegistered, String version ) + { + integration.setRegistered( isRegistered ); + integration.setVersion( version ); + + integration.integrate(); + + register(integration ); + } + + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java index 8a8f27001..9fb735d4a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java @@ -5,6 +5,6 @@ */ public enum IntegrationType { - ECONOMY, PERMISSION, PLACEHOLDER, WORLDGUARD + ECONOMY, PERMISSION, PLACEHOLDER, WORLDGUARD, CUSTOMBLOCK } diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceHolderKey.java b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceHolderKey.java index d7f509358..e2f64a0ad 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceHolderKey.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceHolderKey.java @@ -1,6 +1,6 @@ package tech.mcprison.prison.integration; -import tech.mcprison.prison.integration.IntegrationManager.PrisonPlaceHolders; +import tech.mcprison.prison.integration.PlaceholderManager.PrisonPlaceHolders; public class PlaceHolderKey { diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttribute.java b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttribute.java new file mode 100644 index 000000000..1632f81e4 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttribute.java @@ -0,0 +1,7 @@ +package tech.mcprison.prison.integration; + +public interface PlaceholderAttribute { + + public void parseAttribute( String attribute ); + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttributeNumberFormat.java b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttributeNumberFormat.java new file mode 100644 index 000000000..f4214379c --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderAttributeNumberFormat.java @@ -0,0 +1,7 @@ +package tech.mcprison.prison.integration; + +public class PlaceholderAttributeNumberFormat + // implements PlaceholderAttribute + { + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderManager.java b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderManager.java new file mode 100644 index 000000000..ff9034ec6 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/PlaceholderManager.java @@ -0,0 +1,533 @@ +package tech.mcprison.prison.integration; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.output.Output; + +public class PlaceholderManager { + + public static final String PRISON_PLACEHOLDER_PREFIX = "prison"; + public static final String PRISON_PLACEHOLDER_PREFIX_EXTENDED = PRISON_PLACEHOLDER_PREFIX + "_"; + + public static final String PRISON_PLACEHOLDER_MINENAME_SUFFIX = "_minename"; + public static final String PRISON_PLACEHOLDER_LADDERNAME_SUFFIX = "_laddername"; + + public static final String PRISON_PLACEHOLDER_ATTRIBUTE_SEPARATOR = ":"; + + private PlaceholderProgressBarConfig progressBarConfig; + + public enum PlaceHolderFlags { + + PLAYER, + LADDERS, + MINES, + PLAYERMINES, + + SUPRESS, + ALIAS + ; + } + + public enum PlaceHolderAttributePrefixes { + nFormat + } + + /** + *

The given place holders should have both the prison prefix and without, + * with the without having the suppress value set. The suppressable items + * will not always be displayed since it would be implied that the prefix + * would have been provided. + *

+ * + *

Update: The placeholders without the prison prefix have been eliminated + * since the prefix is now prepended when it is missing prior to matching to a + * valid placeholder enum. This cuts the number of generated placeholders in half. + * This is significant since with the addition of the aliases there would be about + * 744 placeholders generated if the prison had 30 mines setup! Now a 30 mine prison + * would have about 372. + *

+ * + *

Note: In order to use these placeholders with something like holographic display + * you need to also include the placeholderAPI, + * plugin holographic extension and protocolib. + *

+ * + *

In order to get the holographics extension to work it is critical you read + * their spigot page since you have to specify a refresh speed. + *

+ * + * /hd addline temp2 Mine Size: {slowest}{prison_mines_blocks_size_temp2} + * or + * /hd addline temp2 Mine Size: {slowest}{prison_mines_blocks_size_temp2} + * /hd addline temp2 Mine Size: {slowest}%prison_mines_blocks_size_temp2% + * + * + * https://dev.bukkit.org/projects/holographic-displays + * https://www.spigotmc.org/resources/placeholderapi.6245/ + * https://www.spigotmc.org/resources/protocollib.1997/ + * https://www.spigotmc.org/resources/holographicextension.18461/ + */ + public enum PrisonPlaceHolders { + + no_match__(PlaceHolderFlags.SUPRESS), + + // Rank aliases: + prison_r(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rn(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rt(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rc(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rcf(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rcp(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rcb(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rcr(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rcrf(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rr(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_rrt(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + + + prison_rank(prison_r, PlaceHolderFlags.PLAYER), + prison_rank_number(prison_rn, PlaceHolderFlags.PLAYER), + prison_rank_tag(prison_rt, PlaceHolderFlags.PLAYER), + prison_rankup_cost(prison_rc, PlaceHolderFlags.PLAYER), + prison_rankup_cost_formatted(prison_rcf, PlaceHolderFlags.PLAYER), + prison_rankup_cost_percent(prison_rcp, PlaceHolderFlags.PLAYER), + prison_rankup_cost_bar(prison_rcb, PlaceHolderFlags.PLAYER), + prison_rankup_cost_remaining(prison_rcr, PlaceHolderFlags.PLAYER), + prison_rankup_cost_remaining_formatted(prison_rcrf, PlaceHolderFlags.PLAYER), + prison_rankup_rank(prison_rr, PlaceHolderFlags.PLAYER), + prison_rankup_rank_tag(prison_rrt, PlaceHolderFlags.PLAYER), + + + // Ladder aliases: + prison_r_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rn_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rt_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rc_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rcf_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rcp_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rcb_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rcr_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rcrf_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rr_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_rrt_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + + + prison_rank_laddername(prison_r_laddername, PlaceHolderFlags.LADDERS), + prison_rank_number_laddername(prison_rn_laddername, PlaceHolderFlags.LADDERS), + prison_rank_tag_laddername(prison_rt_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_laddername(prison_rc_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_formatted_laddername(prison_rcf_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_percent_laddername(prison_rcp_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_bar_laddername(prison_rcb_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_remaining_laddername(prison_rcr_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_cost_remaining_formatted_laddername(prison_rcrf_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_rank_laddername(prison_rr_laddername, PlaceHolderFlags.LADDERS), + prison_rankup_rank_tag_laddername(prison_rrt_laddername, PlaceHolderFlags.LADDERS), + + + + // player balances. Both with and without ladders. + prison_pb(PlaceHolderFlags.PLAYER, PlaceHolderFlags.ALIAS), + prison_player_balance(prison_pb, PlaceHolderFlags.PLAYER), + + prison_pb_laddername(PlaceHolderFlags.LADDERS, PlaceHolderFlags.ALIAS), + prison_player_balance_laddername(prison_pb_laddername, PlaceHolderFlags.LADDERS), + + + + // Mine aliases: + prison_mn_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mt_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mi_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mif_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mtl_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mtlb_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mtlf_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_ms_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mr_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mrb_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mp_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mpc_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mbm_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + prison_mrc_minename(PlaceHolderFlags.MINES, PlaceHolderFlags.ALIAS), + + + // reset_interval, reset_timeleft, blocks_size, blocks_remaining, blocks_percent + // player_count + // NOTE: Remove PrisonPlaceHolderFlags.SUPRESS when ready to be used: + prison_mines_name_minename(prison_mn_minename, PlaceHolderFlags.MINES), + prison_mines_tag_minename(prison_mt_minename, PlaceHolderFlags.MINES), + prison_mines_interval_minename(prison_mi_minename, PlaceHolderFlags.MINES), + prison_mines_interval_formatted_minename(prison_mif_minename, PlaceHolderFlags.MINES), + prison_mines_timeleft_minename(prison_mtl_minename, PlaceHolderFlags.MINES), + prison_mines_timeleft_bar_minename(prison_mtlb_minename, PlaceHolderFlags.MINES), + prison_mines_timeleft_formatted_minename(prison_mtlf_minename, PlaceHolderFlags.MINES), + prison_mines_size_minename(prison_ms_minename, PlaceHolderFlags.MINES), + prison_mines_remaining_minename(prison_mr_minename, PlaceHolderFlags.MINES), + prison_mines_remaining_bar_minename(prison_mrb_minename, PlaceHolderFlags.MINES), + prison_mines_percent_minename(prison_mp_minename, PlaceHolderFlags.MINES), + prison_mines_player_count_minename(prison_mpc_minename, PlaceHolderFlags.MINES), + prison_mines_blocks_mined_minename(prison_mbm_minename, PlaceHolderFlags.MINES), + prison_mines_reset_count_minename(prison_mrc_minename, PlaceHolderFlags.MINES), + + + + // PlayerMine aliases: + prison_mn_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mt_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mi_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mif_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mtl_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mtlb_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mtlf_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_ms_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mr_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mrb_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mp_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mpc_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mbm_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + prison_mrc_pm(PlaceHolderFlags.PLAYERMINES, PlaceHolderFlags.ALIAS), + + + prison_mines_name_playermines(prison_mn_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_tag_playermines(prison_mt_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_interval_playermines(prison_mi_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_interval_formatted_playermines(prison_mif_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_timeleft_playermines(prison_mtl_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_timeleft_bar_playermines(prison_mtlb_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_timeleft_formatted_playermines(prison_mtlf_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_size_playermines(prison_ms_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_remaining_playermines(prison_mr_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_remaining_bar_playermines(prison_mrb_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_percent_playermines(prison_mp_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_player_count_playermines(prison_mpc_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_blocks_mined_playermines(prison_mbm_pm, PlaceHolderFlags.PLAYERMINES), + prison_mines_reset_count_playermines(prison_mrc_pm, PlaceHolderFlags.PLAYERMINES), + + + + ; + + + private final PrisonPlaceHolders alias; + private final List flags; + private PrisonPlaceHolders() { + this.flags = new ArrayList<>(); + this.alias = null; + } + private PrisonPlaceHolders(PlaceHolderFlags... flags) { + this.alias = null; + this.flags = getFlags(flags); + } + private PrisonPlaceHolders(PrisonPlaceHolders alias, PlaceHolderFlags... flags) { + this.alias = alias; + this.flags = getFlags(flags); + } + + private List getFlags( PlaceHolderFlags[] flags ) { + List flagz = new ArrayList<>(); + if ( flags != null ) { + for ( PlaceHolderFlags flag : flags ) { + flagz.add( flag ); + } + } + return flagz; + } + + public PrisonPlaceHolders getAlias() + { + return alias; + } + + public boolean hasAlias() { + return alias != null; + } + public boolean isAlias() { + return flags.contains( PlaceHolderFlags.ALIAS ); + } + public boolean isSuppressed() { + return flags.contains( PlaceHolderFlags.SUPRESS ); + } + public boolean hasFlag( PlaceHolderFlags flag ) { + return flags.contains( flag ); + } + public List getFlags() { + return flags; + } + + public static PrisonPlaceHolders fromString( String placeHolder ) { + PrisonPlaceHolders result = no_match__; + + if ( placeHolder != null && placeHolder.trim().length() > 0 ) { + placeHolder = placeHolder.trim(); + + // This allows us to get rid of suppressed placeholders that were used for + // internal matching when placeholder APIs strip off the prefix: + if ( !placeHolder.toLowerCase().startsWith( PRISON_PLACEHOLDER_PREFIX ) ) { + placeHolder = PRISON_PLACEHOLDER_PREFIX + "_" + placeHolder; + } + + for ( PrisonPlaceHolders ph : values() ) { + if ( ph.name().equalsIgnoreCase( placeHolder ) ) { + result = ph; + break; + } + } + } + + return result; + } + + public static List getTypes(PlaceHolderFlags flag) { + List results = new ArrayList<>(); + + if ( flag != null ) { + for ( PrisonPlaceHolders ph : values() ) { + if ( ph.getFlags().contains( flag )) { + results.add( ph ); + } + } + } + + return results; + } + + public static List excludeTypes( + List list, PlaceHolderFlags flag) { + List results = new ArrayList<>(); + + if ( flag != null ) { + for ( PrisonPlaceHolders ph : list ) { + if ( !ph.getFlags().contains( flag )) { + results.add( ph ); + } + } + } + + return results; + } + + public String getChatText() { + return "&a" + name() + + (hasAlias() ? "&7(&b" + getAlias().name() + "&7)" : "") + + (isSuppressed() ? "&4*&a ": " "); + } + + public static String getAllChatTexts() { + return getAllChatTexts(false); + } + + public static String getAllChatTextsOmitSuppressable() { + return getAllChatTexts(true); + } + + static List getAllChatList( boolean omitSuppressable) { + List results = new ArrayList<>(); + + boolean hasDeprecated = false; + + for ( PrisonPlaceHolders ph : values() ) + { + if ( !omitSuppressable || omitSuppressable && !ph.isSuppressed() && !ph.isAlias() ) { + if ( !hasDeprecated && ph.isSuppressed() ) { + hasDeprecated = true; + } + + results.add( ph.getChatText() ); + } + } + + if ( hasDeprecated ) { + results.add( " &2(&4*&2=&4suppressed&2)" ); + } + + return results; + } + + private static String getAllChatTexts( boolean omitSuppressable) { + StringBuilder sb = new StringBuilder(); + + List placeholders = getAllChatList(omitSuppressable); + + for ( String placeholder : placeholders ) { + sb.append( placeholder ); + } + + return sb.toString(); + } + + } + + + /** + *

This will extract attributes from dynamic placeholders and will return. + *

+ * + *

Planning on using : as separators. :: for identifying each attribute, and then + * within each attribute : will separate the individual fields and values. + * For example it a number format attribute could look like this: + *

+ * + *
::nFormat:0.00{unit}
for no spaces. + *
::nFormat:#,##0.0+{unit}
for spaces since + will be converted to spaces. + * + * @param placeholder + * @return + */ + public List placeholderExtractAttribute( String placeholder ) { + List results = new ArrayList<>(); + + + return results; + } + + + public void reloadPlaceholderBarConfig() { + setProgressBarConfig( loadPlaceholderBarConfig() ); + } + + public PlaceholderProgressBarConfig loadPlaceholderBarConfig() { + PlaceholderProgressBarConfig config = null; + + String barSegmentsStr = Prison.get().getPlatform().getConfigString( + "placeholder.bar-segments" ); + String barPositiveColor = Prison.get().getPlatform().getConfigString( + "placeholder.bar-positive-color" ); + String barPositiveSegment = Prison.get().getPlatform().getConfigString( + "placeholder.bar-positive-segment" ); + String barNegativeColor = Prison.get().getPlatform().getConfigString( + "placeholder.bar-negative-color" ); + String barNegativeSegment = Prison.get().getPlatform().getConfigString( + "placeholder.bar-negative-segment" ); + + + // All 5 must not be null: + if ( barSegmentsStr != null && barPositiveColor != null && barPositiveSegment != null && + barNegativeColor != null && barNegativeSegment != null ) { + + int barSegments = 20; + + try { + barSegments = Integer.parseInt( barSegmentsStr ); + } + catch ( NumberFormatException e ) { + Output.get().logWarn( + "IntegrationManager.loadPlaceholderBarConfigs(): Failure to convert the" + + "/plugins/Prison/config.yml prison-placeholder-configs.progress-bar.bar-segments " + + "to a valid integer. Defaulting to a value of 20 " + + "[" + barSegmentsStr + "] " + e.getMessage() ); + + } + + config = new PlaceholderProgressBarConfig( barSegments, + barPositiveColor, barPositiveSegment, + barNegativeColor, barNegativeSegment ); + } + + if ( config == null ) { + // go with default values because the config.yml is not up to date with + // the default values + + config = new PlaceholderProgressBarConfig( + 20, "&2", "#", "&4", "=" +// 20, "&2", "▊", "&4", "▒" + ); + + Output.get().logInfo( "The /plugins/Prison/config.yml does not contain the " + + "default values for the Placeholder Progress Bar." ); + Output.get().logInfo( "Default values are " + + "being used. To customize the bar, rename the config.yml and it will be " + + "regenerated and then edit to restore prior values."); + + } + + return config; + } + + public PlaceholderProgressBarConfig getProgressBarConfig() { + if ( progressBarConfig == null ) { + progressBarConfig = loadPlaceholderBarConfig(); + } + return progressBarConfig; + } + public void setProgressBarConfig( PlaceholderProgressBarConfig progressBarConfig ) { + this.progressBarConfig = progressBarConfig; + } + + /** + *

This function uses the settings within the config.yml to construct a progress + * bar. It takes two numeric values and constructs it upon those parameters. + * The parameter

value
is the value that changes, and is the value that + * sets where the bar changes. The parameter
valueTotal
is the max value + * of where the
value
is increasing to. + *

+ * + *

The lowest range is always zero and

value
will be set to zero if + * it is negative. If
value
is greater than
valueTotal
+ * then it will be set to that value. The valid range for this function is only 0 percent + * to 100 percent. + *

+ * + *

If the progress bar is moving in the wrong direction, then set the parameter + *

reverse
to true and then the
value
will be inverted by subtracting + * its value from
valueTotal
. + *

+ * + * @param value A value that is changing. Will be set to zero if negative. Will be + * set to valueTotal if greater than that amount. + * @param valueTotal The target value that is non-changing. + * @param reverse Changes the growth direction of the progress bar. + * @return + */ + public String getProgressBar( double value, double valueTotal, boolean reverse ) { + StringBuilder sb = new StringBuilder(); + + // value cannot be greater than valueTotal: + if ( value > valueTotal ) { + value = valueTotal; + } + else if ( value < 0 ) { + value = 0; + } + + // If reverse, then the new value is subtracted from valueTotal: + if ( reverse ) { + value = valueTotal - value; + } + + double percent = value / valueTotal * 100.0; + + PlaceholderProgressBarConfig barConfig = + Prison.get().getPlaceholderManager().getProgressBarConfig(); + + String lastColorCode = null; + for ( int i = 0; i < barConfig.getSegments(); i++ ) { + double pct = i / ((double)barConfig.getSegments()) * 100.0; + + if ( pct < percent ) { + if ( lastColorCode == null || + !barConfig.getPositiveColor().equalsIgnoreCase( lastColorCode )) { + sb.append( barConfig.getPositiveColor() ); + lastColorCode = barConfig.getPositiveColor(); + } + sb.append( barConfig.getPositiveSegment() ); + } + else { + if ( lastColorCode == null || + !barConfig.getNegativeColor().equalsIgnoreCase( lastColorCode )) { + sb.append( barConfig.getNegativeColor() ); + lastColorCode = barConfig.getNegativeColor(); + } + sb.append( barConfig.getNegativeSegment() ); + + } + } + + + return sb.toString(); + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/Placeholders.java b/prison-core/src/main/java/tech/mcprison/prison/integration/Placeholders.java index 6a417ebb5..b252cfdc9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/Placeholders.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/Placeholders.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.UUID; -import tech.mcprison.prison.integration.IntegrationManager.PlaceHolderFlags; +import tech.mcprison.prison.integration.PlaceholderManager.PlaceHolderFlags; public interface Placeholders { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java b/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java index a4c5d9ee5..87cd350e2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java @@ -18,12 +18,17 @@ package tech.mcprison.prison.internal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.commons.lang3.StringUtils; + import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; -import java.util.*; - /** * Represents an item stack. An item stack is a uniquely named stack in a player's inventory. * @@ -38,6 +43,14 @@ public class ItemStack { private List lore; private Map enchantments; + + protected ItemStack() { + super(); + + this.lore = new ArrayList<>(); + this.enchantments = new HashMap<>(); + } + public ItemStack(String displayName, int amount, BlockType material, String... lore) { this.displayName = displayName; this.amount = amount; @@ -65,7 +78,6 @@ public String getName() { public String getDisplayName() { return displayName; } - public void setDisplayName(String displayName) { this.displayName = displayName; } @@ -76,19 +88,28 @@ public void setDisplayName(String displayName) { public int getAmount() { return amount; } + public void setAmount( int amount ) { + this.amount = amount; + } - /** + /** * Returns the type of items in this stack. */ public BlockType getMaterial() { return material; } + public void setMaterial( BlockType material ) { + this.material = material; + } - public List getLore() { + public List getLore() { return lore; } + public void setLore( List lore ) { + this.lore = lore; + } - public Map getEnchantments() { + public Map getEnchantments() { return enchantments; } @@ -108,7 +129,7 @@ public boolean hasEnchantment(int enchantment) { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (o == null || !(o instanceof ItemStack)) { return false; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java index b803dfd00..f12a92cee 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java @@ -18,14 +18,15 @@ package tech.mcprison.prison.internal; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + import tech.mcprison.prison.internal.inventory.InventoryHolder; import tech.mcprison.prison.internal.scoreboard.Scoreboard; import tech.mcprison.prison.util.Gamemode; import tech.mcprison.prison.util.Location; -import java.util.Optional; -import java.util.UUID; - /** * Represents a player on the Minecraft server. * @@ -125,4 +126,10 @@ public interface Player extends CommandSender, InventoryHolder { */ public void printDebugInventoryInformationToConsole(); + + public List getPermissions(); + + + public List getPermissions( String prefix ); + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/Scheduler.java b/prison-core/src/main/java/tech/mcprison/prison/internal/Scheduler.java index 7eea4e1c3..25124660f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/Scheduler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/Scheduler.java @@ -34,7 +34,7 @@ public interface Scheduler { * @param delay The time to wait, in ticks, until the task is run. * @return The task ID. */ - int runTaskLater(Runnable run, long delay); + public int runTaskLater(Runnable run, long delay); /** * Run a task on its own thread, after a certain amount of time. @@ -43,7 +43,7 @@ public interface Scheduler { * @param delay The time to wait, in ticks, until the task is run. * @return The task ID. */ - int runTaskLaterAsync(Runnable run, long delay); + public int runTaskLaterAsync(Runnable run, long delay); /** * Run a task on the server thread, at the specified interval. @@ -53,7 +53,7 @@ public interface Scheduler { * @param interval The time between runs, in ticks. * @return The task ID. */ - int runTaskTimer(Runnable run, long delay, long interval); + public int runTaskTimer(Runnable run, long delay, long interval); /** * Run a task on its own thread, at the specified interval. @@ -63,18 +63,19 @@ public interface Scheduler { * @param interval The time between runs, in ticks. * @return The task ID. */ - int runTaskTimerAsync(Runnable run, long delay, long interval); + public int runTaskTimerAsync(Runnable run, long delay, long interval); /** * Cancel a certain task. * * @param taskId The task's ID. */ - void cancelTask(int taskId); + public void cancelTask(int taskId); /** * Cancels all tasks registered through this scheduler. */ - void cancelAll(); + public void cancelAll(); + public boolean isPrimaryThread(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java index d00ac9c7c..de1dd596f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java @@ -12,9 +12,13 @@ public class PrisonBlock implements Comparable { + public static PrisonBlock AIR; public static PrisonBlock IGNORE; public static PrisonBlock NULL_BLOCK; + private PrisonBlockType blockType; + private boolean useBlockTypeAsPrefix = false; + private String blockName; private double chance; @@ -25,10 +29,16 @@ public class PrisonBlock private boolean legacyBlock = false; static { + AIR = new PrisonBlock( InternalBlockTypes.AIR.name(), false ); IGNORE = new PrisonBlock( InternalBlockTypes.IGNORE.name(), false ); NULL_BLOCK = new PrisonBlock( InternalBlockTypes.NULL_BLOCK.name(), false ); } + public enum PrisonBlockType { + minecraft, + CustomItems + } + /** * The name of this block should be based upon the XMaterial name in all * lower case. @@ -36,10 +46,14 @@ public class PrisonBlock * @param blockName */ public PrisonBlock( String blockName ) { - this( blockName, 0); + this( PrisonBlockType.minecraft, blockName, 0); } + public PrisonBlock( PrisonBlockType blockType, String blockName ) { + this( blockType, blockName, 0); + } + public PrisonBlock( String blockName, boolean block ) { - this( blockName, 0); + this( PrisonBlockType.minecraft, blockName, 0); this.block = block; } @@ -49,26 +63,95 @@ public PrisonBlock( String blockName, boolean block ) { * @param blockName * @param chance */ - public PrisonBlock( String blockName, double chance ) { + public PrisonBlock( PrisonBlockType blockType, String blockName, double chance ) { super(); + + this.blockType = blockType; this.blockName = blockName.toLowerCase(); this.chance = chance; + } + public PrisonBlock( PrisonBlock clonable ) { + this( clonable.getBlockType(), clonable.getBlockName(), clonable.getChance() ); + + this.useBlockTypeAsPrefix = clonable.isUseBlockTypeAsPrefix(); + this.valid = clonable.isValid(); + this.block = clonable.isBlock(); + this.legacyBlock = clonable.isLegacyBlock(); + } @Override public String toString() { - return getBlockName() + " " + Double.toString( getChance() ); + return getBlockType().name() + ": " + getBlockName() + + ( getChance() > 0 ? " " + Double.toString( getChance()) : ""); } + public PrisonBlockType getBlockType() { + return blockType; + } + public void setBlockType( PrisonBlockType blockType ) { + this.blockType = blockType; + } + public String getBlockName() { return blockName; } public void setBlockName( String blockName ) { this.blockName = blockName; } + + /** + *

This function always prefixes the block name with the BlockType. + * This is critical when saving the block to a file because there + * are no guarantees that when the server restarts the environment + * will be the same. There is a good chance that if new blocks are + * added, or if new plugins are added with new collection of custom + * blocks, then there could be a conflict. There is also the + * chance that a plugin could be removed for a block that's in a + * mine too. + *

+ * + *

So having the BlockType as a prefix will help correctly align + * the blocks back to their proper source. This is critical because + * the correct plugin must handle both the block placements, and also + * the correct plugin must be used when breaking the blocks. + *

+ * + * @return + */ + public String getBlockNameFormal() { + return getBlockType().name() + ":" + getBlockName(); + } + + /** + *

This provides the blockName prefixed with the block type if it is not + * a type of minecraft. + *

+ * + * @return + */ + public String getBlockNameSearch() { + return getBlockType() != PrisonBlockType.minecraft ? + getBlockType().name() + ":" + getBlockName() : getBlockName(); + } + /** + * When adding custom blocks to prison, there is a check to ensure + * that the name is not in conflict with a preexisting block name. + * If there is a conflict, then this field will be set to true and + * then the BlockType will be used as the prefix. + * + * @return + */ + public boolean isUseBlockTypeAsPrefix() { + return useBlockTypeAsPrefix; + } + public void setUseBlockTypeAsPrefix( boolean useBlockTypeAsPrefix ) { + this.useBlockTypeAsPrefix = useBlockTypeAsPrefix; + } + public double getChance() { return chance; } @@ -115,12 +198,16 @@ public void setLegacyBlock( boolean legacyBlock ) { this.legacyBlock = legacyBlock; } + public PrisonBlock clone() { + return new PrisonBlock( this ); + } + @Override public boolean equals( Object block ) { boolean results = false; if ( block != null && block instanceof PrisonBlock) { - results = getBlockName().equalsIgnoreCase( ((PrisonBlock) block).getBlockName() ); + results = getBlockNameFormal().equalsIgnoreCase( ((PrisonBlock) block).getBlockNameFormal() ); } return results; diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java index 8e632784f..362b3d460 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.TreeMap; -import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; /** *

This class is a new way of dealing with blocks within prison. @@ -18,6 +18,7 @@ public class PrisonBlockTypes { private TreeMap blockTypesByName; public enum InternalBlockTypes { + AIR, IGNORE, NULL_BLOCK } @@ -29,24 +30,87 @@ public PrisonBlockTypes() { this.blockTypesByName = new TreeMap<>(); + initializeBlockTypes(); } - public void loadServerBlockTypes() { + /** + *

This internally sets up the internal block types that should be + * accessible to the end users. For example, INGORE needs to be exposed + * so it can be used within mines, but NULL_BLOCK should never be + * exposed since it is used in block caching. At best, it should only + * be just one or a few blocks. + *

+ * + *

When all bukkit blocks are verified and added, it would use the + *

addBlockTypes
to add in those blocks. The bukkit block + * lists must be added prior to any custom blocks. + *

+ */ + private void initializeBlockTypes() { // First clear the blockTypes: getBlockTypes().clear(); - getBlockTypes().add( PrisonBlock.IGNORE ); - // Next using the server's platform, load all of the available blockTypes. - Prison.get().getPlatform().getAllPlatformBlockTypes( getBlockTypes() ); + // Add in prison's internal block types here: + getBlockTypes().add( PrisonBlock.IGNORE ); + // Map all available blocks to the blockTypesByName map: for ( PrisonBlock pb : getBlockTypes() ) { getBlockTypesByName().put( pb.getBlockName().toLowerCase(), pb ); } } + + /** + *

This function adds in supported block types to the listings of + * valid blocks that are available for use on the server instance that + * is being ran. Spigot v1.8.8 will produce a different set of blocks + * than what Spigot v1.16.4 would produce. + *

+ * + *

The bukkit blocks must be added prior to any custom blocks. + * When a block is added, it first confirms if the block name already + * exists. If it does exist, then it sets that block so it will + * automatically use the prefix to make sure it is unique. + *

+ * + * @param blockTypes + */ + public void addBlockTypes( List blockTypes ) { + + // Map all available blocks to the blockTypesByName map: + for ( PrisonBlock pb : blockTypes ) { + + // Check to see if this current block pb already exists, if it does + // then set the prefix usage: + if ( getBlockTypesByName().containsKey( pb.getBlockName().toLowerCase() )) { + + pb.setUseBlockTypeAsPrefix( true ); + } + + getBlockTypesByName().put( pb.getBlockName().toLowerCase(), pb ); + getBlockTypes().add( pb ); + + if ( pb.getBlockType() != PrisonBlockType.minecraft ) { + + getBlockTypesByName().put( pb.getBlockNameSearch().toLowerCase(), pb ); + } + } + } + public List getBlockTypes( String searchTerm ) { + List results = new ArrayList<>(); + + for ( PrisonBlock pBlock : getBlockTypes() ) { + if ( pBlock.isBlock() && + pBlock.getBlockNameSearch().toLowerCase().contains( searchTerm.toLowerCase() )) { + results.add( pBlock ); + } + } + return results; + } + public List getBlockTypes() { return blockTypes; } @@ -54,6 +118,15 @@ public void setBlockTypes( List blockTypes ) { this.blockTypes = blockTypes; } + public PrisonBlock getBlockTypesByName( String blockName ) { + blockName = blockName.toLowerCase(); + if ( blockName.startsWith( PrisonBlockType.minecraft.name() + ":" )) { + blockName = blockName.replaceAll( PrisonBlockType.minecraft.name() + ":", "" ); + } + + PrisonBlock block = blockTypesByName.get( blockName ); + return block == null ? null : block.clone(); + } public TreeMap getBlockTypesByName() { return blockTypesByName; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java index 37d98ca41..4bfc8c618 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java @@ -32,6 +32,7 @@ import tech.mcprison.prison.internal.Scheduler; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.internal.scoreboard.ScoreboardManager; import tech.mcprison.prison.modules.ModuleElement; import tech.mcprison.prison.modules.ModuleElementType; @@ -166,6 +167,8 @@ public interface Platform { public void log(String message, Object... format); public void logCore( String message ); + + public void logPlain( String message ); /** * Logs a debug message to the console if the user has debug messages enabled. @@ -283,8 +286,17 @@ default Optional getCommand(String label) { public boolean getConfigBooleanTrue( String key ); - public void getAllPlatformBlockTypes( List blockTypes ); + public int getConfigInt( String key, int defaultValue ); + + /** + * Setup hooks in to the valid prison block types. This will be only the + * block types that have tested to be valid on the server that is running + * prison. This provides full compatibility to the admins that if a block + * is listed, then it's usable. No more guessing or finding out after the + * fact that a block that was used was invalid for their version of minecraft. + */ + public PrisonBlockTypes getPrisonBlockTypes(); public PrisonBlock getPrisonBlock( String blockName ); @@ -302,6 +314,9 @@ default Optional getCommand(String label) { public void autoCreateMineBlockAssignment(); + + + public void autoCreateMineLinerAssignment(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java index 131683eeb..4c95f0cab 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java @@ -99,14 +99,22 @@ public static File setupDataFolder( String name ) { /** * Called when the module is to be enabled. */ - public void enable() { - } + abstract public void enable(); + + + /** + * This function is called after the modules are enabled and after + * the integrations are enabled. Content in this deferred startup will + * have access to the all of the integrations. + */ + abstract public void deferredStartup(); + /** * Called when a module is to be disabled. */ - public void disable() { - } + abstract public void disable(); + /** * Tell the module loader that this module failed to start. diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java index 82941c26d..c81163d94 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java @@ -57,9 +57,14 @@ public static class BulletedListBuilder { public BulletedListBuilder() { this.bullets = new ArrayList<>(); } - + public BulletedListBuilder add(FancyMessage message) { - bullets.add(message); + bullets.add(message); + return this; + } + + public BulletedListBuilder add(RowComponent row) { + bullets.add( row.getFancy() ); return this; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 71f92a1f7..4efec6bf9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -41,6 +41,8 @@ public class Output { public String ERROR_PREFIX = gen("Error"); public String DEBUG_PREFIX = gen("Debug"); + private boolean debug = false; + // Constructor private Output() { @@ -190,8 +192,21 @@ public void logError(String message, Throwable... throwable) { Arrays.stream(throwable).forEach(Throwable::printStackTrace); } } + + public void logDebug(String message, Object... args) { + if ( isDebug() ) { + log(message, LogLevel.DEBUG, args); + } + } + + public boolean isDebug() { + return debug; + } + public void setDebug( boolean debug ) { + this.debug = debug; + } - /** + /** * Send a message to a {@link CommandSender} */ public void sendMessage(CommandSender sender, String message, LogLevel level, Object... args) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonRunnable.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonRunnable.java new file mode 100644 index 000000000..652ace449 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonRunnable.java @@ -0,0 +1,6 @@ +package tech.mcprison.prison.tasks; + +public interface PrisonRunnable + extends Runnable { + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java new file mode 100644 index 000000000..04d093a01 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java @@ -0,0 +1,90 @@ +package tech.mcprison.prison.tasks; + +import tech.mcprison.prison.Prison; + +public class PrisonTaskSubmitter { + + /** + * Run a task on the server thread, after a certain amount of time. + * + * @param task The {@link Runnable} with the task inside. + * @param delayInTicks The time to wait, in ticks, until the task is run. + * @return The task ID. + */ + public static int runTaskLater( PrisonRunnable task, long delayInTicks ) { + int taskId = Prison.get().getPlatform().getScheduler().runTaskLater(task, delayInTicks); + + return taskId; + } + + + /** + * Run a task on its own thread, after a certain amount of time. + * + * @param task The {@link Runnable} with the task inside. + * @param delayInTicks The time to wait, in ticks, until the task is run. + * @return The task ID. + */ + public static int runTaskLaterAsync(Runnable task, long delayInTicks) { + int taskId = Prison.get().getPlatform().getScheduler().runTaskLaterAsync(task, delayInTicks); + + return taskId; + } + + /** + * Run a task on the server thread, at the specified interval. + * + * @param task The {@link Runnable} with the task inside. + * @param delayInTicks The time to wait, in ticks, until the timer is started. + * @param intervalInTicks The time between runs, in ticks. + * @return The task ID. + */ + public static int runTaskTimer(Runnable task, long delayInTicks, long intervalInTicks){ + int taskId = Prison.get().getPlatform().getScheduler().runTaskTimer(task, delayInTicks, + intervalInTicks); + + return taskId; + } + + /** + * Run a task on its own thread, at the specified interval. + * + * @param task The {@link Runnable} with the task inside. + * @param delayInTicks The time to wait, in ticks, until the timer is started. + * @param intervalInTicks The time between runs, in ticks. + * @return The task ID. + */ + public static int runTaskTimerAsync(Runnable task, long delayInTicks, long intervalInTicks){ + int taskId = Prison.get().getPlatform().getScheduler().runTaskTimerAsync(task, delayInTicks, + intervalInTicks); + + return taskId; + } + + /** + * Cancel a certain task. + * + * @param taskId The task's ID. + */ + public static void cancelTask(int taskId) { + Prison.get().getPlatform().getScheduler().cancelTask( taskId ); + } + + /** + * Cancels all tasks registered through this scheduler. + */ + public static void cancelAll(){ + Prison.get().getPlatform().getScheduler().cancelAll(); + } + + /** + * Check to see if this is running in Bukkit's primary thread, if not + * then it indicates its running as an async mode. + * + * @return + */ + public static boolean isPrimaryThread() { + return Prison.get().getPlatform().getScheduler().isPrimaryThread(); + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/BlockType.java b/prison-core/src/main/java/tech/mcprison/prison/util/BlockType.java index a64284978..1f511e421 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/BlockType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/BlockType.java @@ -1049,7 +1049,7 @@ public enum BlockType { TWISTING_VINES( "minecraft:twisting_vines", MaterialType.BLOCK, MaterialVersion.v1_16 ), - WEAPING_VINES( "minecraft:weaping_vines", MaterialType.BLOCK, MaterialVersion.v1_16 ), + WEEPING_VINES( "minecraft:weeping_vines", MaterialType.BLOCK, MaterialVersion.v1_16 ), diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java index 1c91a43f5..34d0eb490 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java @@ -42,11 +42,25 @@ public class Text { millisPerDay, "hours", millisPerHour, "minutes", millisPerMinute, "seconds", millisPerSecond); private static String headingLine = repeat("-", 52); + private static final char COLOR_CHAR = '\u00A7'; - private static final Pattern STRIP_COLOR_PATTERN = - Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]"); - - private Text() { + private static final String COLOR_ = String.valueOf(COLOR_CHAR); + + public static final Pattern STRIP_COLOR_PATTERN = + Pattern.compile("(?i)" + COLOR_ + "#[A-Fa-f0-9]{6}|" + + COLOR_ + "[0-9A-FK-OR]"); + + + public static final Pattern STRIP_COLOR_PATTERN_ORIGINAL = + Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]"); + + + //#([A-Fa-f0-9]){6} + + + protected Text() { + super(); + } /** @@ -205,14 +219,16 @@ public static String translateColorCodes(String text, char prefix) { } char[] b = text.toCharArray(); + boolean dirty = false; for (int i = 0; i < b.length - 1; ++i) { - if (b[i] == prefix && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) { + if (b[i] == prefix && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr#xX".indexOf(b[i + 1]) > -1) { b[i] = 167; // Section symbol b[i + 1] = Character.toLowerCase(b[i + 1]); + dirty = true; } } - return new String(b); + return dirty ? new String(b) : text; } /** diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java index 3f0d1ad53..4f98485ca 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java @@ -31,13 +31,14 @@ import tech.mcprison.prison.commands.PluginCommand; import tech.mcprison.prison.file.FileStorage; import tech.mcprison.prison.file.YamlFileIO; -import tech.mcprison.prison.integration.IntegrationManager.PlaceHolderFlags; +import tech.mcprison.prison.integration.PlaceholderManager.PlaceHolderFlags; import tech.mcprison.prison.integration.Placeholders; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.Scheduler; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.internal.platform.Capability; import tech.mcprison.prison.internal.platform.Platform; import tech.mcprison.prison.internal.scoreboard.ScoreboardManager; @@ -152,6 +153,11 @@ public void logCore( String message ) { System.out.println(ChatColor.stripColor(message)); } + @Override + public void logPlain( String message ) { + System.out.println(message); + } + @Override public void debug(String message, Object... format) { log(message, format); } @@ -240,10 +246,14 @@ public boolean getConfigBooleanTrue( String key ) { } @Override - public void getAllPlatformBlockTypes( List blockTypes ) { - + public int getConfigInt( String key, int defaultValue ) { + return defaultValue; } + @Override + public PrisonBlockTypes getPrisonBlockTypes() { + return null; + } @Override public PrisonBlock getPrisonBlock( String blockName ) { @@ -276,4 +286,9 @@ public void autoCreateMineBlockAssignment() { } + @Override + public void autoCreateMineLinerAssignment() { + + } + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java index 175704655..84d5ec933 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java @@ -18,6 +18,12 @@ package tech.mcprison.prison; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.inventory.Inventory; @@ -25,8 +31,6 @@ import tech.mcprison.prison.util.Gamemode; import tech.mcprison.prison.util.Location; -import java.util.*; - /** * @author Faizaan A. Datoo */ @@ -124,4 +128,25 @@ public List getInput() { public void printDebugInventoryInformationToConsole() { } + + @Override + public List getPermissions() { + List results = new ArrayList<>(); + + return results; + } + + @Override + public List getPermissions( String prefix ) { + List results = new ArrayList<>(); + + for ( String perm : getPermissions() ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; + } + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java b/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java index 59fa4d0eb..2ad6dd8c4 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java @@ -29,4 +29,9 @@ public class TestScheduler implements Scheduler { @Override public void cancelAll() { } + + @Override + public boolean isPrimaryThread() { + return false; + } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java new file mode 100644 index 000000000..fedca7241 --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java @@ -0,0 +1,49 @@ +package tech.mcprison.prison.util; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class TextTest + extends Text +{ + + @Test + public void testStripColor() { + // +// public static final Pattern STRIP_COLOR_PATTERN = +// Pattern.compile("(?i)" + COLOR_ + "#[A-Fa-f0-9]{6}|" + +// COLOR_ + "[0-9A-FK-OR]"); + + assertEquals("This is a test", stripColor("This is a test")); + assertEquals("This is a test", stripColor("This &7is a test")); + assertEquals("This is a test", stripColor("This &7is &Ra test")); + assertEquals("This is a test", stripColor("This &7is &ra test")); + + assertEquals("This is a test", stripColor("This &0&1&2&3&4&5&6&7&8&9" + + "&a&A&B&b&c&C&d&D&e&E&f&F&k&K&l&L&m&M&n&N&o&O&r&Ris &Ra test")); + + assertEquals("This is a test", stripColor("&KTh&ris &7is &aa &At&Be&8s&9t")); + + assertEquals("This is a test", stripColor("This 𞉀is &ra test")); + assertEquals("This is a test", stripColor("This &#abCDeFis &ra test")); + + + } + + public void testTranslateAmpColorCodes() { + assertEquals("This is a test", translateColorCodes("This is a test", 'x')); + assertEquals("This x7is a test", translateColorCodes("This &7is a test", 'x')); + assertEquals("This x7is xRa test", translateColorCodes("This &7is &Ra test", 'x')); + assertEquals("This x7is xra test", translateColorCodes("This &7is &ra test", 'x')); + + + assertEquals("xKThxris x7is xaa xAtxBex8sx9t", + translateColorCodes("&KTh&ris &7is &aa &At&Be&8s&9t", 'x')); + + assertEquals("This x#123456is xra test", translateColorCodes("This 𞉀is &ra test", 'x')); + assertEquals("This x#abCDeFis &xra test", translateColorCodes("This &#abCDeFis &ra test", 'x')); + + + } +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java index 43f390df5..7defa42e5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java @@ -25,7 +25,6 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; -import tech.mcprison.prison.convert.ConversionManager; import tech.mcprison.prison.error.ErrorManager; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.Player; @@ -36,7 +35,6 @@ import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; -import tech.mcprison.prison.mines.managers.PlayerManager; import tech.mcprison.prison.modules.Module; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.store.Database; @@ -60,7 +58,7 @@ public class PrisonMines extends Module { private JsonFileIO jsonFileIO; private MineManager mineManager; - private PlayerManager player; +// private PlayerManager player; private MinesCommands minesCommands; @@ -93,6 +91,7 @@ public String getBaseCommands() { return "&7/&2mines"; } + @Override public void enable() { i = this; @@ -106,9 +105,10 @@ public void enable() { // initWorlds(); this.mineManager = new MineManager(); - getMineManager().loadFromDbCollection(this); +// getMineManager().loadFromDbCollection(this); - player = new PlayerManager(); + // Player manager for mines is not used. +// this.player = new PlayerManager(); // initMines(); PrisonAPI.getEventBus().register(new MinesListener()); @@ -118,11 +118,40 @@ public void enable() { Prison.get().getCommandHandler().registerCommands( getMinesCommands() ); //Prison.get().getCommandHandler().registerCommands(new PowertoolCommands()); - ConversionManager.getInstance().registerConversionAgent(new MinesConversionAgent()); + + // This is obsolete and was part of converting from pre-v3.0: + // ConversionManager.getInstance().registerConversionAgent(new MinesConversionAgent()); } - private void initDb() { + /** + * This function deferredStartup() will be called after the integrations have been + * loaded. + * + */ + @Override + public void deferredStartup() { + // Load the mines at this time. + getMineManager().loadFromDbCollection(this); + + } + + /** + *

Mines are now saved whenever changes are made. Do not save the Mines on server + * shutdown since they will never be in a dirty state; they will always be saved. + *

+ * + *

This should shutdown all active mines. Future to do item. + *

+ * + */ + @Override + public void disable() { + // Nothing to do... + } + + + private void initDb() { Optional dbOptional = Prison.get().getPlatform().getStorage().getDatabase("mines"); @@ -213,15 +242,6 @@ public JsonFileIO getJsonFileIO() return jsonFileIO; } - /** - *

Mines are now saved whenever changes are made. Do not save the Mines on server - * shutdown since they will never be in a dirty state; they will always be saved. - *

- * - */ - public void disable() { - // Nothing to do... - } public MinesConfig getConfig() { return config; @@ -255,9 +275,9 @@ public LocaleManager getMinesMessages() { // return worlds; // } - public PlayerManager getPlayerManager() { - return player; - } +// public PlayerManager getPlayerManager() { +// return player; +// } public MinesCommands getMinesCommands() { return minesCommands; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 9e19a58b9..ef848440f 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -38,13 +38,16 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Block; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.data.MineData; import tech.mcprison.prison.mines.data.MineData.MineNotificationMode; -import tech.mcprison.prison.mines.data.MineLinerBuilder; -import tech.mcprison.prison.mines.data.MineLinerBuilder.LinerPatterns; +import tech.mcprison.prison.mines.features.MineBlockEvent; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.mines.features.MineLinerBuilder; +import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; @@ -410,13 +413,18 @@ public void addBlockCommand(CommandSender sender, // return; // } - if ( Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ) ) { + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); + + + if ( useNewBlockModel ) { block = block == null ? null : block.trim().toLowerCase(); PrisonBlock prisonBlock = null; - if ( block != null && Prison.get().getPrisonBlockTypes().getBlockTypesByName().containsKey( block ) ) { - prisonBlock = Prison.get().getPrisonBlockTypes().getBlockTypesByName().get( block ); + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + + if ( block != null && prisonBlockTypes.getBlockTypesByName().containsKey( block ) ) { + prisonBlock = prisonBlockTypes.getBlockTypesByName().get( block ); } if ( prisonBlock == null ) { @@ -489,7 +497,7 @@ else if ( chance <= 0 ) { .withReplacements(block, mineName).sendTo(sender); } - getBlocksList(m, null).send(sender); + getBlocksList(m, null, useNewBlockModel).send(sender); //pMines.getMineManager().clearCache(); } @@ -523,7 +531,7 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr if ( chance <= 0 ) { // remove the block since it has zero chance - m.getPrisonBlocks().remove( existingPrisonBlock ); + m.removePrisonBlock( existingPrisonBlock ); } else { // update chance for the prisonBlock. This block is @@ -538,7 +546,7 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr } else { prisonBlock.setChance( chance ); - m.getPrisonBlocks().add( prisonBlock ); + m.addPrisonBlock( prisonBlock ); pMines.getMineManager().saveMine( m ); @@ -572,14 +580,18 @@ public void setBlockCommand(CommandSender sender, // return; // } - if ( Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ) ) { + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); + + if ( useNewBlockModel ) { block = block == null ? null : block.trim().toLowerCase(); PrisonBlock prisonBlock = null; - if ( block != null && Prison.get().getPrisonBlockTypes().getBlockTypesByName().containsKey( block ) ) { - prisonBlock = Prison.get().getPrisonBlockTypes().getBlockTypesByName().get( block ); + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + + if ( block != null && prisonBlockTypes.getBlockTypesByName().containsKey( block ) ) { + prisonBlock = prisonBlockTypes.getBlockTypesByName().get( block ); } @@ -690,7 +702,7 @@ public void setBlockCommand(CommandSender sender, } - getBlocksList(m, null).send(sender); + getBlocksList(m, null, useNewBlockModel ).send(sender); //pMines.getMineManager().clearCache(); @@ -711,9 +723,6 @@ private BlockPercentTotal calculatePercentage( double chance, BlockType blockTyp } } - if ( results.getOldBlock() == null ) { - results.setOldBlock( new Block(blockType, chance) ); - } return results; } @@ -787,15 +796,19 @@ public void delBlockCommand(CommandSender sender, PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(mineName); + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); - if ( Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ) ) { + if ( useNewBlockModel ) { block = block == null ? null : block.trim().toLowerCase(); PrisonBlock prisonBlock = null; - if ( block != null && Prison.get().getPrisonBlockTypes().getBlockTypesByName().containsKey( block ) ) { - prisonBlock = Prison.get().getPrisonBlockTypes().getBlockTypesByName().get( block ); + + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + + if ( block != null && prisonBlockTypes.getBlockTypesByName().containsKey( block ) ) { + prisonBlock = prisonBlockTypes.getBlockTypesByName().get( block ); } // Cannot delete a block if it does not exist: @@ -830,7 +843,7 @@ public void delBlockCommand(CommandSender sender, deleteBlock( sender, pMines, m, blockType ); } - getBlocksList(m, null).send(sender); + getBlocksList(m, null, useNewBlockModel).send(sender); } /** @@ -841,16 +854,8 @@ public void delBlockCommand(CommandSender sender, * @param m * @param prisonBlock */ - private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, PrisonBlock prisonBlock ) - { - PrisonBlock rBlock = null; - for ( PrisonBlock block : m.getPrisonBlocks() ) { - if (block.getBlockName().equalsIgnoreCase( prisonBlock.getBlockName() )) { - rBlock = block; - break; - } - } - if ( m.getPrisonBlocks().remove( rBlock )) { + private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, PrisonBlock prisonBlock ) { + if ( m.removePrisonBlock( prisonBlock ) ) { pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_deleted"). @@ -912,13 +917,9 @@ public void searchBlockCommand(CommandSender sender, private ChatDisplay prisonBlockSearchBuilder(String search, String page) { - List blocks = new ArrayList<>(); - for ( PrisonBlock pBlock : Prison.get().getPrisonBlockTypes().getBlockTypes() ) { - if ( pBlock.isBlock() && pBlock.getBlockName().contains( search.toLowerCase() )) { - blocks.add( pBlock ); - } - } + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + List blocks = prisonBlockTypes.getBlockTypes( search ); CommandPagedData cmdPageData = new CommandPagedData( "/mines block search " + search, blocks.size(), @@ -952,11 +953,11 @@ private ChatDisplay prisonBlockSearchBuilder(String search, String page) FancyMessage msg = new FancyMessage( String.format("&7%s %s", - Integer.toString(i), block.getBlockName() + Integer.toString(i), block.getBlockNameSearch() // block.getAltName(), )) .suggest("/mines block add " + getLastMineReferenced() + - " " + block.getBlockName() + " %") + " " + block.getBlockNameSearch() + " %") .tooltip("&7Click to add block to a mine."); builder.add(msg); } @@ -1119,7 +1120,7 @@ public void deleteCommand(CommandSender sender, public void infoCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to view.") String mineName, @Arg(name = "page", def = "1", - description = "Page of search results (optional) [1-n, ALL]") String page + description = "Page of search results (optional) [1-n, ALL, DEBUG]") String page ) { if (!performCheckMineExists(sender, mineName)) { return; @@ -1226,7 +1227,58 @@ public void infoCommand(CommandSender sender, } } + +// chatDisplay.text("&3Size: &7%d&8x&7%d&8x&7%d", Math.round(m.getBounds().getWidth()), +// Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength())); + + if ( !m.isVirtual() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Size: &7%d&8x&7%d&8x&7%d", Math.round(m.getBounds().getWidth()), + Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength()) ); + + row.addTextComponent( " &3Volume: &7%s &3Blocks", + dFmt.format( Math.round(m.getBounds().getTotalBlockCount())) ); + chatDisplay.addComponent( row ); + } + + + if ( !m.isVirtual() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Blocks Remaining: &7%s %s%% ", + dFmt.format( m.getRemainingBlockCount() ), + fFmt.format( m.getPercentRemainingBlockCount() ) ); + + chatDisplay.addComponent( row ); + } + + + { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Liner: &7%s", + m.getLinerData().toInfoString() ); + chatDisplay.addComponent( row ); + } + + + + { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Command Count: &7%d", + m.getResetCommands().size() ); + chatDisplay.addComponent( row ); + } + + + + { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine BlockEvent Count: &7%d", + m.getBlockEvents().size() ); + chatDisplay.addComponent( row ); + } + + { RowComponent row = new RowComponent(); double rtMinutes = m.getResetTime() / 60.0D; @@ -1288,29 +1340,7 @@ public void infoCommand(CommandSender sender, - -// chatDisplay.text("&3Size: &7%d&8x&7%d&8x&7%d", Math.round(m.getBounds().getWidth()), -// Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength())); - - if ( !m.isVirtual() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Size: &7%d&8x&7%d&8x&7%d", Math.round(m.getBounds().getWidth()), - Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength()) ); - - row.addTextComponent( " &3Volume: &7%s &3Blocks", - dFmt.format( Math.round(m.getBounds().getTotalBlockCount())) ); - chatDisplay.addComponent( row ); - } - - - if ( !m.isVirtual() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Blocks Remaining: &7%s %s%% ", - dFmt.format( m.getRemainingBlockCount() ), - fFmt.format( m.getPercentRemainingBlockCount() ) ); - - chatDisplay.addComponent( row ); - } + { RowComponent row = new RowComponent(); @@ -1387,37 +1417,60 @@ public void infoCommand(CommandSender sender, } - if ( cmdPageData.isShowAll() || cmdPageData.getCurPage() > 1 ) { - chatDisplay.text("&3Blocks:"); - chatDisplay.text("&8Click on a block's name to edit its chances of appearing."); - BulletedListComponent list = getBlocksList(m, cmdPageData); - - chatDisplay.addComponent(list); - } - - int blockSize = 0; + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); - if ( Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ) ) { - blockSize = m.getPrisonBlocks().size(); + if ( useNewBlockModel ) { + + if ( cmdPageData.isDebug() ) { + chatDisplay.text( "&7Block model: &3New" ); + } + + if ( cmdPageData.isShowAll() || cmdPageData.getCurPage() > 1 ) { + chatDisplay.text("&3Blocks:"); + chatDisplay.text("&8Click on a block's name to edit its chances of appearing."); + BulletedListComponent list = getBlocksList(m, cmdPageData, true ); + + chatDisplay.addComponent(list); + } + + int blockSize = m.getPrisonBlocks().size(); + + String message = blockSize != 0 ? null : " &cNo Blocks Defined"; + cmdPageData.generatePagedCommandFooter( chatDisplay, message ); + } - else { - blockSize = m.getBlocks().size(); + if ( !useNewBlockModel || useNewBlockModel && cmdPageData.isDebug() ) { + + if ( cmdPageData.isDebug() ) { + chatDisplay.text( "&7Block model: &3Old" ); + } + + if ( cmdPageData.isShowAll() || cmdPageData.getCurPage() > 1 ) { + chatDisplay.text("&3Blocks:"); + chatDisplay.text("&8Click on a block's name to edit its chances of appearing."); + BulletedListComponent list = getBlocksList(m, cmdPageData, false ); + + chatDisplay.addComponent(list); + } + + int blockSize = m.getBlocks().size(); + + String message = blockSize != 0 ? null : " &cNo Blocks Defined"; + cmdPageData.generatePagedCommandFooter( chatDisplay, message ); } - String message = blockSize != 0 ? null : " &cNo Blocks Defined"; - cmdPageData.generatePagedCommandFooter( chatDisplay, message ); chatDisplay.send(sender); } - private BulletedListComponent getBlocksList(Mine m, CommandPagedData cmdPageData) { + private BulletedListComponent getBlocksList(Mine m, CommandPagedData cmdPageData, boolean useNewBlockModel) { BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); DecimalFormat dFmt = new DecimalFormat("##0.00"); double totalChance = 0.0d; int count = 0; - if ( Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ) ) { + if ( useNewBlockModel ) { for (PrisonBlock block : m.getPrisonBlocks()) { double chance = Math.round(block.getChance() * 100.0d) / 100.0d; @@ -1436,7 +1489,8 @@ private BulletedListComponent getBlocksList(Mine m, CommandPagedData cmdPageData } } } - else { + if ( !useNewBlockModel || + !useNewBlockModel && cmdPageData != null && cmdPageData.isDebug() ) { for (Block block : m.getBlocks()) { double chance = Math.round(block.getChance() * 100.0d) / 100.0d; @@ -1663,7 +1717,7 @@ private BulletedListComponent getMinesLineItemList( PrisonSortableResults sorted if ( m.isUsePagingOnReset() ) { row.addFancy( - new FancyMessage("&5Pgd ") + new FancyMessage("&5Paged ") .tooltip("&7Paging Used during Mine Reset")); } @@ -2388,10 +2442,10 @@ public void setTracerCommand(CommandSender sender, @Command(identifier = "mines set size", permissions = "mines.set", description = "Change the size of the mine") public void setSizeCommand(CommandSender sender, - @Arg(name = "mineName", description = "The name of the mine to set the tracer in.") String mineName, + @Arg(name = "mineName", description = "The name of the mine to resize.") String mineName, @Arg(name = "edge", description = "Edge to adjust [top, bottom, north, east, south, west, walls]", def = "walls") String edge, //@Arg(name = "adjustment", description = "How to adust the size [smaller, larger]", def = "larger") String adjustment, - @Arg(name = "amount", description = "amount to adjust, [-1, 1]", def = "1") int amount + @Arg(name = "amount", description = "amount to adjust, [-1, 0, 1]. Zero will refresh liner.", def = "1") int amount ) { @@ -2406,8 +2460,8 @@ public void setSizeCommand(CommandSender sender, } if ( amount == 0 ) { - sender.sendMessage( "&cInvalid amount. Cannot be zero." ); - return; + sender.sendMessage( "&cSize of mine will not be changed. Will refresh the liner." ); +// return; } // if ( adjustment == null || "smaller".equalsIgnoreCase( adjustment ) || "larger".equalsIgnoreCase( adjustment ) ) { @@ -2519,15 +2573,16 @@ else if ( "force".equalsIgnoreCase( force ) ) { PrisonMines pMines = PrisonMines.getInstance(); Mine mine = pMines.getMine(mineName); - if ( mine.isVirtual() ) { - sender.sendMessage( "&cMine is a virtual mine.&7 Use &a/mines set area &7to enable the mine." ); - return; - } +// if ( mine.isVirtual() ) { +// sender.sendMessage( "&cMine is a virtual mine.&7 Use &a/mines set area &7to enable the mine." ); +// return; +// } + mine.getLinerData().setLiner( e, linerPattern, isForced ); new MineLinerBuilder( mine, e, linerPattern, isForced ); - // NOTE: The mine itself was not changed, so nothing to save: + pMines.getMineManager().saveMine( mine ); } @@ -2783,6 +2838,493 @@ public void playerInventoryCommand(CommandSender sender) { } + + + @Command(identifier = "mines blockEvent list", description = "Lists the blockEvent commands for a mine.", + onlyPlayers = false, permissions = "mines.set") + public void blockEventList(CommandSender sender, + @Arg(name = "mineName") String mineName) { + + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if (m.getBlockEvents() == null || m.getBlockEvents().size() == 0) { + Output.get().sendInfo(sender, "The mine '%s' contains no BlockEvent commands.", m.getName()); + return; + } + + + ChatDisplay display = new ChatDisplay("BlockEvent Commands for " + m.getName()); + display.text("&8Click a BlockEvent command to remove it."); + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); + + DecimalFormat dFmt = new DecimalFormat("0.00000"); + + int rowNumber = 1; + for (MineBlockEvent blockEvent : m.getBlockEvents()) { + + RowComponent row = new RowComponent(); + + String chance = dFmt.format( blockEvent.getChance() ); + + row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); + + FancyMessage msgPercent = new FancyMessage( String.format( "&7%s%% ", chance ) ) + .command( "/mines blockEvent percent " + mineName + " " + rowNumber + " " ) + .tooltip("Percent Chance - Click to Edit"); + row.addFancy( msgPercent ); + + FancyMessage msgPerm = new FancyMessage( String.format( "&3[&7%s&3] ", + blockEvent.getPermission() ) ) + .command( "/mines blockEvent permission " + mineName + " " + rowNumber + " " ) + .tooltip("Permission - Click to Edit"); + row.addFancy( msgPerm ); + + FancyMessage msgEventType = new FancyMessage( String.format( "&7%s ", + blockEvent.getEventType().name() ) ) + .command( "/mines blockEvent eventType " + mineName + " " + rowNumber + " " ) + .tooltip("Event Type - Click to Edit"); + row.addFancy( msgEventType ); + + FancyMessage msgMode = new FancyMessage( String.format( "&3(&7%s&3) ", + blockEvent.getMode() ) ) + .command( "/mines blockEvent mode " + mineName + " " + rowNumber + " " ) + .tooltip("Event Mode - Click to Edit"); + row.addFancy( msgMode ); + + FancyMessage msgCommand = new FancyMessage( String.format( " &a'&7%s&a'", + blockEvent.getCommand() ) ) + .command("/mines blockEvent remove " + mineName + " " + blockEvent.getCommand() ) + .tooltip("Event Commands - Click to Delete"); + row.addFancy( msgCommand ); + + + + builder.add( row ); + } + + display.addComponent(builder.build()); + display.addComponent(new FancyMessageComponent( + new FancyMessage("&7[&a+&7] Add").suggest("/mines blockEvent add " + mineName + " [chance] [perm] [cmd] /") + .tooltip("&7Add a new BockEvent command."))); + display.send(sender); + } + + + @Command(identifier = "mines blockEvent remove", description = "Removes a BlockEvent command from a mine.", + onlyPlayers = false, permissions = "mines.set") + public void blockEventRemove(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "command", description = "Exact BlockEvent command to remove") + @Wildcard String command) { + + if (command.startsWith("/")) { + command = command.replaceFirst("/", ""); + } + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); + Mine m = pMines.getMine(mineName); + + + if (m.getBlockEvents() == null || m.getBlockEvents().size() == 0) { + Output.get().sendInfo(sender, "The mine '%s' contains no BlockEvent commands.", m.getName()); + return; + } + + if ( m.getBlockEventsRemove(command) ) { + + pMines.getMineManager().saveMine( m ); + + Output.get().sendInfo(sender, "Removed BlockEvent command '%s' from the mine '%s'.", + command, m.getName()); + } else { + Output.get().sendWarn(sender, + String.format("The mine %s doesn't contain that BlockEvent command. Nothing was changed.", + m.getName())); + } + + // Redisplay the event list: + blockEventList( sender, mineName ); + } + + + + @Command(identifier = "mines blockEvent add", description = "Adds a BlockBreak command to a mine. " + + "Can use placeholders {player} and {player_uid}. Use ; between multiple commands.", + onlyPlayers = false, permissions = "mines.set") + public void blockEventAdd(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "percent", + description = "Percent chance between 0.0000 and 100.0") Double chance, + @Arg(name = "permission", def = "none", + description = "Optional permission that the player must have, or [none] for no perm." + ) String perm, + @Arg(name = "eventType", def = "eventTypeAll", + description = "EventType to trigger BlockEvent: [eventTypeAll, eventBlockBreak, eventTEXplosion]" + ) String eventType, + @Arg(name = "mode", description = "Processing mode to run the task: [inline, sync]", + def = "inline") String mode, + @Arg(name = "command") @Wildcard String command) { + + // Note: async is not an option since the bukkit dispatchCommand will run it as sync. + //String mode = "sync"; + + if (command.startsWith("/")) { + command = command.replaceFirst("/", ""); + } + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + if ( chance <= 0d || chance > 100.0d ) { + sender.sendMessage( + String.format("&7Please provide a valid value for chance " + + "between 0.0000 and 100.0. Was state=[&b%d&7]", + chance )); + return; + } + + if ( mode == null || !"sync".equalsIgnoreCase( mode ) && !"inline".equalsIgnoreCase( mode ) ) { + sender.sendMessage( + String.format("&7Please provide a valid mode for running the commands. " + + "[inline, sync] mode=[&b%s&7]", + mode )); + return; + } + + if ( perm == null || perm.trim().length() == 0 || "none".equalsIgnoreCase( perm ) ) { + perm = ""; + } + + + BlockEventType eType = BlockEventType.fromString( eventType ); + if ( !eType.name().equalsIgnoreCase( eventType ) ) { + sender.sendMessage( + String.format("&7Notice: The supplied eventType does not match the list of valid " + + "BlockEventTypes therefore defaulting to eventTypeAll. Valid eventTypes are: " + + "[eventTypeAll, eventBlockBreak, eventTEXplosion]", + eventType )); + } + + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if ( command == null || command.trim().length() == 0 ) { + sender.sendMessage( + String.format( "&7Please provide a valid BlockEvent command: command=[%s]", command) ); + return; + } + + MineBlockEvent blockEvent = new MineBlockEvent( chance, perm, command, mode, eType ); + m.getBlockEvents().add( blockEvent ); + + pMines.getMineManager().saveMine( m ); + + Output.get().sendInfo(sender, "&7Added BlockEvent command '&b%s&7' for eventTypes of " + + "&b%s &7to the mine '&b%s&7' with " + + "the optional permission %s. Using the mode %s.", + command, eType.name(), m.getName(), + perm == null || perm.trim().length() == 0 ? "&3none&7" : "'&3" + perm + "&7'", + mode ); + + + // Redisplay the event list: + blockEventList( sender, mineName ); + + } + + + @Command(identifier = "mines blockEvent percent", + description = "Edits the percentage amount", + onlyPlayers = false, permissions = "mines.set") + public void blockEventPercent(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "row") Integer row, + @Arg(name = "percent", + description = "Percent chance between 0.0000 and 100.0") Double chance) { + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + if ( row == null || row <= 0 ) { + sender.sendMessage( + String.format("&7Please provide a valid row number greater than zero. " + + "Was row=[&b%d&7]", + (row == null ? "null" : row) )); + return; + } + + if ( chance <= 0d || chance > 100.0d ) { + sender.sendMessage( + String.format("&7Please provide a valid value for chance " + + "between 0.0000 and 100.0. Was state=[&b%d&7]", + chance )); + return; + } + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if ( row > m.getBlockEvents().size() ) { + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; + } + + MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); + + double chanceOld = blockEvent.getChance(); + + // Update percent: + blockEvent.setChance( chance ); + + // Save the mine: + pMines.getMineManager().saveMine( m ); + + DecimalFormat dFmt = new DecimalFormat("0.00000"); + Output.get().sendInfo(sender, "&7BlockEvent percentage &b%s&7 was changed for mine '&b%s&7'. " + + "Was &b%s&7. Command '&b%s&7'", + dFmt.format( chance ), m.getName(), + dFmt.format( chanceOld ), blockEvent.getCommand() ); + + // Redisplay the event list: + blockEventList( sender, mineName ); + + } + + + @Command(identifier = "mines blockEvent permission", description = "Edits a BlockBreak permisson.", + onlyPlayers = false, permissions = "mines.set") + public void blockEventPermission(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "row") Integer row, + @Arg(name = "permission", def = "none", + description = "Optional permission that the player must have, or [none] for no perm." + ) String perm + ) { + + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + + if ( row == null || row <= 0 ) { + sender.sendMessage( + String.format("&7Please provide a valid row number greater than zero. " + + "Was row=[&b%d&7]", + (row == null ? "null" : row) )); + return; + } + + + if ( perm == null || perm.trim().length() == 0 || "none".equalsIgnoreCase( perm ) ) { + perm = ""; + } + + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if ( row > m.getBlockEvents().size() ) { + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; + } + + MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); + + String permissionOld = blockEvent.getPermission(); + + blockEvent.setPermission( perm ); + + pMines.getMineManager().saveMine( m ); + + + Output.get().sendInfo(sender, "&7BlockEvent permission &b%s&7 was changed for mine '&b%s&7'. " + + "Was &b%s&7. Command '&b%s&7'", + perm == null || perm.trim().length() == 0 ? "&3none&7" : "'&3" + perm + "&7'", + m.getName(), + permissionOld == null || permissionOld.trim().length() == 0 ? "&3none&7" : + "'&3" + permissionOld + "&7'", + blockEvent.getCommand() ); + + + // Redisplay the event list: + blockEventList( sender, mineName ); + + } + + + @Command(identifier = "mines blockEvent eventType", description = "Edits a BlockBreak EventType.", + onlyPlayers = false, permissions = "mines.set") + public void blockEventEventType(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "row") Integer row, + @Arg(name = "eventType", def = "eventTypeAll", + description = "EventType to trigger BlockEvent: " + + "[eventTypeAll, eventBlockBreak, eventTEXplosion]" + ) String eventType + ) { + + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + + if ( row == null || row <= 0 ) { + sender.sendMessage( + String.format("&7Please provide a valid row number greater than zero. " + + "Was row=[&b%d&7]", + (row == null ? "null" : row) )); + return; + } + + + BlockEventType eType = BlockEventType.fromString( eventType ); + if ( !eType.name().equalsIgnoreCase( eventType ) ) { + sender.sendMessage( + String.format("&7Notice: The supplied eventType does not match the list of valid " + + "BlockEventTypes therefore defaulting to eventTypeAll. Valid eventTypes are: " + + "[eventTypeAll, eventBlockBreak, eventTEXplosion]", + eventType )); + } + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if ( row > m.getBlockEvents().size() ) { + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; + } + + MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); + + BlockEventType eTypeOld = blockEvent.getEventType(); + + blockEvent.setEventType( eType ); + + pMines.getMineManager().saveMine( m ); + + + Output.get().sendInfo(sender, "&7BlockEvent EventType &b%s&7 was changed for mine '&b%s&7'. " + + "Was &b%s&7. Command '&b%s&7'", + eType.name(), m.getName(), eTypeOld.name(), blockEvent.getCommand() ); + + + // Redisplay the event list: + blockEventList( sender, mineName ); + + } + + + @Command(identifier = "mines blockEvent mode", description = "Edits a BlockBreak mode type: [inline, sync].", + onlyPlayers = false, permissions = "mines.set") + public void blockEventJobMode(CommandSender sender, + @Arg(name = "mineName") String mineName, + @Arg(name = "row") Integer row, + @Arg(name = "mode", description = "Processing mode to run the task: [inline, sync]", + def = "inline") String mode + ) { + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + + if ( row == null || row <= 0 ) { + sender.sendMessage( + String.format("&7Please provide a valid row number greater than zero. " + + "Was row=[&b%d&7]", + (row == null ? "null" : row) )); + return; + } + + if ( mode == null || !"sync".equalsIgnoreCase( mode ) && !"inline".equalsIgnoreCase( mode ) ) { + sender.sendMessage( + String.format("&7Please provide a valid mode for running the commands. " + + "[inline, sync] mode=[&b%s&7]", + mode )); + return; + } + + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); +// MineManager mMan = pMines.getMineManager(); + Mine m = pMines.getMine(mineName); + + if ( row > m.getBlockEvents().size() ) { + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; + } + + MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); + + String modeOld = blockEvent.getMode(); + + blockEvent.setMode( mode ); + + pMines.getMineManager().saveMine( m ); + + + Output.get().sendInfo(sender, "&7BlockEvent mode &b%s&7 was changed for mine '&b%s&7'. " + + "Was &b%s&7. Command '&b%s&7'", + mode, m.getName(), modeOld, blockEvent.getCommand() ); + + + // Redisplay the event list: + blockEventList( sender, mineName ); + + } + + + + + @Command(identifier = "mines command list", description = "Lists the commands for a mine.", onlyPlayers = false, permissions = "mines.command") diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/PowertoolCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/PowertoolCommands.java index 62844427e..3f442a2ad 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/PowertoolCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/PowertoolCommands.java @@ -1,10 +1,6 @@ package tech.mcprison.prison.mines.commands; import tech.mcprison.prison.commands.BaseCommands; -import tech.mcprison.prison.commands.Command; -import tech.mcprison.prison.internal.CommandSender; -import tech.mcprison.prison.internal.Player; -import tech.mcprison.prison.mines.PrisonMines; public class PowertoolCommands extends BaseCommands { @@ -13,45 +9,45 @@ public PowertoolCommands() { super("PowertoolCommands"); } - @Command(identifier = "autosmelt", description = "Enables/disables the autosmelt tool.", permissions = "mines.autosmelt") - public void autosmeltCommand(CommandSender sender) { - PrisonMines pMines = PrisonMines.getInstance(); - if (!pMines.getPlayerManager().hasAutosmelt((Player) sender)) { - pMines.getPlayerManager().setAutosmelt((Player) sender, true); - pMines.getMinesMessages().getLocalizable("autosmelt_enabled") - .sendTo(sender); - } else { - pMines.getPlayerManager().setAutosmelt((Player) sender, false); - pMines.getMinesMessages().getLocalizable("autosmelt_disabled") - .sendTo(sender); - } - } - - @Command(identifier = "autoblock", description = "Enables/disables the autoblock tool.", permissions = "mines.autoblock") - public void autoblockCommand(CommandSender sender) { - PrisonMines pMines = PrisonMines.getInstance(); - if (!pMines.getPlayerManager().hasAutoblock((Player) sender)) { - pMines.getPlayerManager().setAutoblock((Player) sender, true); - pMines.getMinesMessages().getLocalizable("autoblock_enabled") - .sendTo(sender); - } else { - pMines.getPlayerManager().setAutoblock((Player) sender, false); - pMines.getMinesMessages().getLocalizable("autoblock_disabled") - .sendTo(sender); - } - } - - @Command(identifier = "autopickup", description = "Enables/disables the autopickup tool.", permissions = "mines.autopickup") - public void autopickupCommand(CommandSender sender) { - PrisonMines pMines = PrisonMines.getInstance(); - if (!pMines.getPlayerManager().hasAutopickup((Player) sender)) { - pMines.getPlayerManager().setAutopickup((Player) sender, true); - pMines.getMinesMessages().getLocalizable("autopickup_enabled") - .sendTo(sender); - } else { - pMines.getPlayerManager().setAutopickup((Player) sender, false); - pMines.getMinesMessages().getLocalizable("autopickup_disabled") - .sendTo(sender); - } - } +// @Command(identifier = "autosmelt", description = "Enables/disables the autosmelt tool.", permissions = "mines.autosmelt") +// public void autosmeltCommand(CommandSender sender) { +// PrisonMines pMines = PrisonMines.getInstance(); +// if (!pMines.getPlayerManager().hasAutosmelt((Player) sender)) { +// pMines.getPlayerManager().setAutosmelt((Player) sender, true); +// pMines.getMinesMessages().getLocalizable("autosmelt_enabled") +// .sendTo(sender); +// } else { +// pMines.getPlayerManager().setAutosmelt((Player) sender, false); +// pMines.getMinesMessages().getLocalizable("autosmelt_disabled") +// .sendTo(sender); +// } +// } +// +// @Command(identifier = "autoblock", description = "Enables/disables the autoblock tool.", permissions = "mines.autoblock") +// public void autoblockCommand(CommandSender sender) { +// PrisonMines pMines = PrisonMines.getInstance(); +// if (!pMines.getPlayerManager().hasAutoblock((Player) sender)) { +// pMines.getPlayerManager().setAutoblock((Player) sender, true); +// pMines.getMinesMessages().getLocalizable("autoblock_enabled") +// .sendTo(sender); +// } else { +// pMines.getPlayerManager().setAutoblock((Player) sender, false); +// pMines.getMinesMessages().getLocalizable("autoblock_disabled") +// .sendTo(sender); +// } +// } +// +// @Command(identifier = "autopickup", description = "Enables/disables the autopickup tool.", permissions = "mines.autopickup") +// public void autopickupCommand(CommandSender sender) { +// PrisonMines pMines = PrisonMines.getInstance(); +// if (!pMines.getPlayerManager().hasAutopickup((Player) sender)) { +// pMines.getPlayerManager().setAutopickup((Player) sender, true); +// pMines.getMinesMessages().getLocalizable("autopickup_enabled") +// .sendTo(sender); +// } else { +// pMines.getPlayerManager().setAutopickup((Player) sender, false); +// pMines.getMinesMessages().getLocalizable("autopickup_disabled") +// .sendTo(sender); +// } +// } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index fc428ed3d..cd21cf3bb 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -29,6 +29,8 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.MineException; import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.features.MineBlockEvent; +import tech.mcprison.prison.mines.features.MineLinerData; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.selection.Selection; @@ -193,10 +195,11 @@ private void loadFromDocument( Document document ) World world = null; if ( !isVirtual() ) { - if ( worldName == null ) { - Output.get().logInfo( "Mines.loadFromDocument: Failure: World does not exist in Mine file. mine= %s " + + if ( worldName == null || "Virtually-Undefined".equalsIgnoreCase( worldName ) ) { + Output.get().logInfo( "Mines.loadFromDocument: Failure: World does not exist in Mine " + + "file. mine= %s world= %s " + "Contact support on how to fix.", - getName()); + getName(), (world == null ? "null" : world )); } Optional worldOptional = Prison.get().getPlatform().getWorld(worldName); @@ -359,7 +362,7 @@ else if (validateBlockNames.contains( blockTypeName ) ) { if ( prisonBlock.isLegacyBlock() ) { dirty = true; } - getPrisonBlocks().add( prisonBlock ); + addPrisonBlock( prisonBlock ); validateBlockNames.add( blockTypeName ); } @@ -383,7 +386,7 @@ else if (validateBlockNames.contains( blockTypeName ) ) { if ( prisonBlock != null ) { prisonBlock.setChance( block.getChance() ); - getPrisonBlocks().add( prisonBlock ); + addPrisonBlock( prisonBlock ); dirty = true; } @@ -401,6 +404,20 @@ else if (validateBlockNames.contains( blockTypeName ) ) { Boolean usePagingOnReset = (Boolean) document.get( "usePagingOnReset" ); setUsePagingOnReset( usePagingOnReset == null ? false : usePagingOnReset.booleanValue() ); + + List mineBlockEvents = (List) document.get("mineBlockEvents"); + if ( mineBlockEvents != null ) { + for ( String blockEvent : mineBlockEvents ) { + getBlockEvents().add( MineBlockEvent.fromSaveString( blockEvent ) ); + } + } + + + String mineLinerData = (String) document.get("mineLinerData"); + setLinerData( MineLinerData.fromSaveString( mineLinerData ) ); + + + if ( dirty ) { // Resave the mine data since an update to the mine format was detected and @@ -429,7 +446,8 @@ public Document toDocument() { // If world name is not set, try to get it from the bounds: String worldName = getWorldName(); - if ( worldName == null || worldName.trim().length() == 0 && + if ( (worldName == null || worldName.trim().length() == 0 || + "Virtually-Undefined".equalsIgnoreCase( worldName )) && getBounds() != null && getBounds().getMin() != null && getBounds().getMin().getWorld() != null ) { worldName = getBounds().getMin().getWorld().getName(); @@ -495,8 +513,8 @@ public Document toDocument() { List prisonBlockStrings = new ArrayList<>(); for (PrisonBlock pBlock : getPrisonBlocks() ) { if ( !validateBlockNames.contains( pBlock.getBlockName()) ) { - prisonBlockStrings.add(pBlock.getBlockName() + "-" + pBlock.getChance()); - validateBlockNames.add( pBlock.getBlockName() ); + prisonBlockStrings.add(pBlock.getBlockNameFormal() + "-" + pBlock.getChance()); + validateBlockNames.add( pBlock.getBlockNameFormal() ); } } @@ -514,6 +532,16 @@ public Document toDocument() { ret.put("rank", rank ); } + List mineBlockEvents = new ArrayList<>(); + for ( MineBlockEvent blockEvent : getBlockEvents() ) { + mineBlockEvents.add( blockEvent.toSaveString() ); + } + ret.put("mineBlockEvents", mineBlockEvents); + + + String mineLinerData = getLinerData().toSaveString(); + ret.put("mineLinerData", mineLinerData ); + return ret; } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineCountAirBlocksAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineCountAirBlocksAsyncTask.java index a66cf57f9..c33831f4d 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineCountAirBlocksAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineCountAirBlocksAsyncTask.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.mines.data; +import tech.mcprison.prison.tasks.PrisonRunnable; + public class MineCountAirBlocksAsyncTask implements PrisonRunnable { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index eb1788be5..d28e828ac 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -2,13 +2,18 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; +import tech.mcprison.prison.mines.features.MineBlockEvent; +import tech.mcprison.prison.mines.features.MineLinerData; import tech.mcprison.prison.modules.ModuleElement; import tech.mcprison.prison.modules.ModuleElementType; import tech.mcprison.prison.output.Output; @@ -54,9 +59,30 @@ public abstract class MineData private long targetResetTime; private int resetCount = 0; + /** + * This list of blocks represents the old Prison block model. It is being + * phased out since it has limited flexibility and complex issues with + * supporting magic values with the older bukkit versions. + */ private List blocks; + + /** + * This list of PrisonBlocks represents the new Prison block model. Its + * more flexible and able to support other plugins's custom blocks and + * the core bukkit blocks are based upon Cryptomorin's XSeries' XMaterial + * for greater flexibility and cross version support. + */ private List prisonBlocks; + /** + * To better identify if custom blocks need to be checked upon block break + * events since the custom plugins will have to identify their own blocks, + * this set contains the collection of non-minecraft PrisonBlockTypes that + * are used in this mine. That way it's a simple and fast check to see if, + * and more importantly, which custom block plugin needs to be checked. + */ + private transient Set prisonBlockTypes; + private long totalBlocksMined = 0; private double zeroBlockResetDelaySec; @@ -79,6 +105,11 @@ public abstract class MineData * The rankString are the components of the ModuleElement. */ private String rankString; + + + private List blockEvents; + + private MineLinerData linerData; public enum MineNotificationMode { @@ -114,6 +145,8 @@ public MineData() { this.blocks = new ArrayList<>(); this.prisonBlocks = new ArrayList<>(); + this.prisonBlockTypes = new HashSet<>(); + this.enabled = false; this.virtual = false; @@ -146,6 +179,10 @@ public MineData() { this.rank = null; this.rankString = null; + + this.blockEvents = new ArrayList<>(); + + this.linerData = new MineLinerData(); } /** @@ -315,7 +352,8 @@ public void setBounds(Bounds bounds) { this.bounds = bounds; if ( bounds != null && ( isVirtual() || !getWorld().isPresent() || - getWorldName() == null || getWorldName().trim().length() == 0 ) ) { + getWorldName() == null || getWorldName().trim().length() == 0 || + getWorldName().equalsIgnoreCase( "Virtually-Undefined" )) ) { World world = bounds.getMin().getWorld(); @@ -353,7 +391,41 @@ public List getPrisonBlocks() { return prisonBlocks; } + + public Set getPrisonBlockTypes() { + return prisonBlockTypes; + } + + public void addPrisonBlock( PrisonBlock prisonBlock ) { + if ( prisonBlock != null && !isInMine( prisonBlock )) { + + getPrisonBlocks().add( prisonBlock ); + addPrisonBlockType( prisonBlock ); + } + } + + private void addPrisonBlockType( PrisonBlock prisonBlock ) { + if ( !getPrisonBlockTypes().contains( prisonBlock.getBlockType() )) { + getPrisonBlockTypes().add( prisonBlock.getBlockType() ); + } + } + public boolean removePrisonBlock( PrisonBlock prisonBlock ) { + boolean results = false; + + if ( prisonBlock != null && isInMine( prisonBlock ) ) { + + results = getPrisonBlocks().remove( prisonBlock ); + + // regenerate the PrisonBlockTypes in case the removed block was the last type in the mine + getPrisonBlockTypes().clear(); + for ( PrisonBlock pBlock : getPrisonBlocks() ) { + addPrisonBlockType( pBlock ); + } + } + return results; + } + /** * This is only used in an obsolete conversion utility. * @@ -387,6 +459,7 @@ public boolean isInMine(Location location) { } public boolean isInMine(BlockType blockType) { + //TODO Not sure if virtual should return false... they do have blocks. if ( isVirtual() ) { return false; } @@ -397,13 +470,14 @@ public boolean isInMine(BlockType blockType) { } return false; } - + public boolean isInMine(PrisonBlock blockType) { + //TODO Not sure if virtual should return false... they do have blocks. if ( isVirtual() ) { return false; } for (PrisonBlock block : getPrisonBlocks()) { - if (blockType.getBlockName().equalsIgnoreCase( block.getBlockName())) { + if (blockType.getBlockNameFormal().equalsIgnoreCase( block.getBlockNameFormal())) { return true; } } @@ -414,7 +488,7 @@ public PrisonBlock getPrisonBlock( PrisonBlock blockType ) { PrisonBlock results = null; for (PrisonBlock block : getPrisonBlocks()) { - if (blockType.getBlockName().equalsIgnoreCase( block.getBlockName())) { + if (blockType.getBlockNameFormal().equalsIgnoreCase( block.getBlockNameFormal())) { results = block; break; } @@ -630,5 +704,35 @@ public String getRankString() { public void setRankString( String rankString ) { this.rankString = rankString; } + + public List getBlockEvents() { + return blockEvents; + } + public void setBlockEvents( List blockEvents ) { + this.blockEvents = blockEvents; + } + + public boolean getBlockEventsRemove( String command ) { + boolean results = false; + MineBlockEvent blockEvent = null; + for ( MineBlockEvent be : getBlockEvents() ) { + if ( be.getCommand().equalsIgnoreCase( command ) ) { + blockEvent = be; + } + } + + if ( blockEvent != null ) { + results = getBlockEvents().remove( blockEvent ); + } + + return results; + } + + public MineLinerData getLinerData() { + return linerData; + } + public void setLinerData( MineLinerData linerData ) { + this.linerData = linerData; + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 75aa7ba93..1a0c2254b 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -12,12 +12,18 @@ import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; -import tech.mcprison.prison.internal.block.PrisonBlockTypes.InternalBlockTypes; import tech.mcprison.prison.mines.PrisonMines; -import tech.mcprison.prison.mines.data.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.mines.data.MineScheduler.MineJob; import tech.mcprison.prison.mines.events.MineResetEvent; +import tech.mcprison.prison.mines.features.MineLinerBuilder; +import tech.mcprison.prison.mines.features.MineMover; +import tech.mcprison.prison.mines.features.MineTargetBlock; +import tech.mcprison.prison.mines.features.MineTargetBlockKey; +import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; +import tech.mcprison.prison.mines.features.MineTracerBuilder; +import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Bounds; import tech.mcprison.prison.util.Bounds.Edges; @@ -45,6 +51,19 @@ public abstract class MineReset *

*/ public static final long MINE_RESET__MAX_PAGE_ELASPSED_TIME_MS = 75; + + + /** + *

This is the time in ticks that is used when submitting + * the reset jobs. A value of 0 could cause the server to lock up since + * it does not have enough time to deal with other tasks. + *

+ * + *

One tick is 50 milliseconds, 2 is 100 milliseconds or 1/10 of + * a second. + *

+ */ + public static final long MINE_RESET__PAGE_SUBMIT_DELAY_TICKS = 1; /** *

When placing blocks, this is the block count that is used to check for @@ -228,38 +247,50 @@ private void resetSynchonouslyInternal() { // for (int y = getBounds().getyBlockMin(); y <= getBounds().getyBlockMax(); y++) { for (int x = getBounds().getxBlockMin(); x <= getBounds().getxBlockMax(); x++) { for (int z = getBounds().getzBlockMin(); z <= getBounds().getzBlockMax(); z++) { - Location targetBlock = new Location(world, x, y, z); + Location targetLocation = new Location(world, x, y, z); + + tech.mcprison.prison.internal.block.Block targetBlock = targetLocation.getBlockAt(); if ( useNewBlockModel ) { + PrisonBlock prisonBlock = targetBlock.isEmpty() ? null : + targetBlock.getPrisonBlock(); + if (!isFillMode || - isFillMode && targetBlock.getBlockAt().isEmpty() || - isFillMode && targetBlock.equals(altTp) && - altTp.getBlockAt().getPrisonBlock().getBlockName().equalsIgnoreCase( "GLASS" ) ) { + isFillMode && prisonBlock == null || + isFillMode && targetLocation.equals(altTp) && + prisonBlock.getBlockName().equalsIgnoreCase( "GLASS" ) || + isFillMode && targetLocation.equals(altTp) && + prisonBlock.getBlockName().equalsIgnoreCase( "AIR" ) ) { - - targetBlock.getBlockAt().setPrisonBlock( randomlySelectPrisonBlock( random )); + PrisonBlock targetPrisonBlock = randomlySelectPrisonBlock( random ); + if ( !targetPrisonBlock.equals( PrisonBlock.IGNORE ) ) { + + targetBlock.setPrisonBlock( randomlySelectPrisonBlock( random )); + } i++; + // targetBlock.getBlockAt().setType(getRandomizedBlocks().get(i++)); } - if ( targetBlock.getBlockAt().getPrisonBlock().getBlockName().equalsIgnoreCase( "AIR" ) ) { + if ( prisonBlock == null || + prisonBlock.getBlockName().equalsIgnoreCase( "AIR" ) ) { incrementBlockBreakCount(); } } else { if (!isFillMode || - isFillMode && targetBlock.getBlockAt().isEmpty() || - isFillMode && targetBlock.equals(altTp) && altTp.getBlockAt().getType() == BlockType.GLASS ) { + isFillMode && targetBlock.isEmpty() || + isFillMode && targetLocation.equals(altTp) && altTp.getBlockAt().getType() == BlockType.GLASS ) { - targetBlock.getBlockAt().setType(randomlySelectBlock( random )); + targetBlock.setType(randomlySelectBlock( random )); i++; // targetBlock.getBlockAt().setType(getRandomizedBlocks().get(i++)); } - if ( targetBlock.getBlockAt().getType() == BlockType.AIR ) { + if ( targetBlock.getType() == BlockType.AIR ) { incrementBlockBreakCount(); } } @@ -341,8 +372,10 @@ public String statsMessage() { sb.append( "&3 ResetPages: &7" ); sb.append( iFmt.format(getStatsResetPages() )); - double avgBlocks = getStatsResetPageBlocks() / getStatsResetPages(); - double avgMs = getStatsResetPageMs() / getStatsResetPages(); + double avgBlocks = getStatsResetPages() == 0 ? 0 : + getStatsResetPageBlocks() / getStatsResetPages(); + double avgMs = getStatsResetPages() == 0 ? 0 : + getStatsResetPageMs() / getStatsResetPages(); sb.append( "&3 avgBlocks: &7" ); sb.append( dFmt.format(avgBlocks)); @@ -565,6 +598,9 @@ protected void generateBlockListAsync() { // Clear the mineTargetBlocks list: getMineTargetBlocks().clear(); + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); + + // // Reset the mineAirBlocks to all false values: // boolean[] mAirBlocks = new boolean[ getBounds().getTotalBlockCount() ]; // // Arrays.fill( mAirBlocks, false ); // redundant but prevents nulls if were Boolean @@ -576,17 +612,34 @@ protected void generateBlockListAsync() { for (int x = getBounds().getxBlockMin(); x <= getBounds().getxBlockMax(); x++) { for (int z = getBounds().getzBlockMin(); z <= getBounds().getzBlockMax(); z++) { - BlockType blockType = randomlySelectBlock( random ); + MineTargetBlock mtb = null; - MineTargetBlock mtb = new MineTargetBlock( blockType, x, y, z); + if ( useNewBlockModel ) { + + PrisonBlock prisonBlock = randomlySelectPrisonBlock( random ); + + mtb = new MineTargetPrisonBlock( prisonBlock, x, y, z); + + if ( prisonBlock.equals( PrisonBlock.AIR ) ) { +// mAirBlocks[i++] = true; + airCount++; + } + } + else { + + BlockType blockType = randomlySelectBlock( random ); + + mtb = new MineTargetBlock( blockType, x, y, z); + + if ( blockType == BlockType.AIR ) { +// mAirBlocks[i++] = true; + airCount++; + } + } getMineTargetBlocks().add( mtb ); getMineTargetBlocksMap().put( mtb.getBlockKey(), mtb ); - if ( blockType == BlockType.AIR ) { -// mAirBlocks[i++] = true; - airCount++; - } } } } @@ -840,6 +893,10 @@ private void resetAsynchonouslyUpdate() { else { World world = getBounds().getCenter().getWorld(); + boolean useNewBlockModel = Prison.get().getPlatform().getConfigBooleanFalse( "use-new-prison-block-model" ); + + + long start = System.currentTimeMillis(); boolean isFillMode = PrisonMines.getInstance().getConfig().fillMode; @@ -857,8 +914,16 @@ private void resetAsynchonouslyUpdate() { target.getBlockKey().getZ()); if (!isFillMode || isFillMode && targetBlock.getBlockAt().isEmpty()) { - targetBlock.getBlockAt().setType(target.getBlockType()); } + if ( useNewBlockModel ) { + MineTargetPrisonBlock pbTarget = (MineTargetPrisonBlock) target; + + targetBlock.getBlockAt().setPrisonBlock( pbTarget.getPrisonBlock() ); + } + else { + + targetBlock.getBlockAt().setType(target.getBlockType()); + } /** * About every 250 blocks, or so, check to see if the current wall time @@ -909,11 +974,11 @@ private void resetAsynchonouslyUpdate() { * @param callbackAsync */ public void submitAsyncTask( PrisonRunnable callbackAsync ) { - Prison.get().getPlatform().getScheduler().runTaskLaterAsync( callbackAsync, 0L ); + Prison.get().getPlatform().getScheduler().runTaskLaterAsync( callbackAsync, MINE_RESET__PAGE_SUBMIT_DELAY_TICKS ); } public void submitSyncTask( PrisonRunnable callbackSync ) { - Prison.get().getPlatform().getScheduler().runTaskLater( callbackSync, 0L ); + Prison.get().getPlatform().getScheduler().runTaskLater( callbackSync, MINE_RESET__PAGE_SUBMIT_DELAY_TICKS ); } // /** @@ -993,8 +1058,7 @@ protected void refreshAirCountAsyncTask() } else if ( useNewBlockModel && getPrisonBlocks().size() == 1 && - getPrisonBlocks().get( 0 ).getBlockName().equalsIgnoreCase( InternalBlockTypes.IGNORE.name() ) && - getPrisonBlocks().get( 0 ).getChance() == 100.0 ) { + getPrisonBlocks().get( 0 ).equals( PrisonBlock.IGNORE ) ) { // This mine is set to ignore all blocks when trying to do a reset, // so for now ignore the types and just set air count to zero. @@ -1004,8 +1068,7 @@ else if ( useNewBlockModel && } else if ( !useNewBlockModel && getBlocks().size() == 1 && - getBlocks().get( 0 ).getType() == BlockType.IGNORE && - getBlocks().get( 0 ).getChance() == 100.0 ) { + getBlocks().get( 0 ).getType() == BlockType.IGNORE ) { // This mine is set to ignore all blocks when trying to do a reset, // so for now ignore the types and just set air count to zero. @@ -1032,7 +1095,8 @@ else if ( !useNewBlockModel && if ( useNewBlockModel ) { - if ( targetBlock.getBlockAt().getPrisonBlock().getBlockName().equalsIgnoreCase( "AIR" ) ) { + if ( targetBlock.getBlockAt().getPrisonBlock() == null || + targetBlock.getBlockAt().getPrisonBlock().equals( PrisonBlock.AIR ) ) { airCount++; } } @@ -1055,7 +1119,7 @@ else if ( !useNewBlockModel && String message = String.format( "MineReset.refreshAirCountAsyncTask: Error counting air blocks: " + "Mine=%s coords=%s Error: %s ", getName(), coords, e.getMessage() ); - if ( e.getMessage().contains( "Asynchronous entity world add" )) { + if ( e.getMessage() != null && e.getMessage().contains( "Asynchronous entity world add" )) { Output.get().logWarn( message ); } else { Output.get().logWarn( message, e ); @@ -1153,32 +1217,34 @@ public void refreshMineAsyncResubmitTask() { } - /** - * Generates blocks for the specified mine and caches the result. - * - * The random chance is now calculated upon a double instead of integer. - * - * @param mine the mine to randomize - */ - private void generateBlockList() { - long start = System.currentTimeMillis(); - - Random random = new Random(); - - - getRandomizedBlocks().clear(); - - for (int i = 0; i < getBounds().getTotalBlockCount(); i++) { - BlockType blockType = randomlySelectBlock( random ); - getRandomizedBlocks().add(blockType); - } - long stop = System.currentTimeMillis(); - - setStatsBlockGenTimeMS( stop - start ); - -// Output.get().logInfo("&cMine reset: " + getName() + " generated " + getBounds().getTotalBlockCount() + -// " blocks in " + getStatsBlockGenTimeMS() + " ms"); - } +// NOTE: Obsolete: the reset is no longer using a generated block list since it does not +// provide much of a performance improvement for the cost of the memory it uses. +// /** +// * Generates blocks for the specified mine and caches the result. +// * +// * The random chance is now calculated upon a double instead of integer. +// * +// * @param mine the mine to randomize +// */ +// private void generateBlockList() { +// long start = System.currentTimeMillis(); +// +// Random random = new Random(); +// +// +// getRandomizedBlocks().clear(); +// +// for (int i = 0; i < getBounds().getTotalBlockCount(); i++) { +// BlockType blockType = randomlySelectBlock( random ); +// getRandomizedBlocks().add(blockType); +// } +// long stop = System.currentTimeMillis(); +// +// setStatsBlockGenTimeMS( stop - start ); +// +//// Output.get().logInfo("&cMine reset: " + getName() + " generated " + getBounds().getTotalBlockCount() + +//// " blocks in " + getStatsBlockGenTimeMS() + " ms"); +// } private PrisonBlock randomlySelectPrisonBlock( Random random ) @@ -1331,6 +1397,8 @@ public void adjustSize( Edges edge, int amount ) { // First clear the mine: clearMine( false ); + // if amount is zero, then just refresh the liner: + if ( amount < 0 ) { while ( amount++ < 0 ) { @@ -1342,13 +1410,24 @@ public void adjustSize( Edges edge, int amount ) { new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); } } - else { + else if ( amount > 0 ) { new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); Bounds newBounds = new Bounds( getBounds(), edge, amount ); setBounds( newBounds ); } + // Rebuild the liner if it exists: + for ( Edges targtEdge : Edges.values() ) { + + if ( getLinerData().hasEdge( targtEdge ) ) { + + LinerPatterns pattern = LinerPatterns.fromString( getLinerData().getEdge( targtEdge ) ); + boolean force = getLinerData().getForce( targtEdge ); + + new MineLinerBuilder( (Mine) this, targtEdge, pattern, force ); + } + } // Finally trace the mine: clearMine( true ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java index c00e1d0a9..55602b4b5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.mines.data; +import tech.mcprison.prison.tasks.PrisonRunnable; + public class MineResetAsyncResubmitTask implements PrisonRunnable { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncTask.java index bdb0c88bb..85f24788e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncTask.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.mines.data; +import tech.mcprison.prison.tasks.PrisonRunnable; + public class MineResetAsyncTask implements PrisonRunnable { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index 67a67276b..416e6e7c2 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -1,15 +1,22 @@ package tech.mcprison.prison.mines.data; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Random; import java.util.Stack; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.features.MineBlockEvent; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; public abstract class MineScheduler extends MineReset @@ -394,7 +401,7 @@ private void submitTask() { // Submit currentJob using delay in the job. Must be a one time run, no repeats. - int taskId = Prison.get().getPlatform().getScheduler().runTaskLater(this, ticksToWait); + int taskId = PrisonTaskSubmitter.runTaskLater(this, ticksToWait); setTaskId( taskId ); } else { Output.get().logError("Mine " + getName() + @@ -415,16 +422,16 @@ public void terminateJob() { int taskId = getTaskId(); - Prison.get().getPlatform().getScheduler().cancelTask( taskId ); + PrisonTaskSubmitter.cancelTask( taskId ); } - public void submit( int offset ) { - submitNextAction(offset); + public void submit( double offsetSeconds ) { + submitNextAction(offsetSeconds); } private void submitNextAction() { submitNextAction(0); } - private void submitNextAction(int offset) { + private void submitNextAction(double offsetSeconds) { if ( getJobStack().size() == 0 ) { resetJobStack(); } @@ -432,8 +439,8 @@ private void submitNextAction(int offset) { setCurrentJob( getJobStack().pop() ); // Offset tries to stagger the mine resets, assuming most will have the same delays: - if ( offset > 0 ) { - getCurrentJob().setDelayActionSec( getCurrentJob().getDelayActionSec() + offset ); + if ( offsetSeconds > 0 ) { + getCurrentJob().setDelayActionSec( getCurrentJob().getDelayActionSec() + offsetSeconds ); } // Submit currentJob using delay in the job. Must be a one time run, no repeats. @@ -453,16 +460,103 @@ public void manualReset() { } + /** + *

This function checks if the block break event should execute a + * given command or not. If it needs to, then it will submit them to run as + * a task instead of running them in this thread. + *

+ * + * @param blockCount + * @param player + */ + public void processBlockBreakEventCommands( int blockCount, Player player, BlockEventType eventType ) { + + if ( getBlockEvents().size() > 0 ) { + Random random = new Random(); + + for ( int i = 0; i < blockCount; i ++ ) { + double chance = random.nextDouble() * 100; + + for ( MineBlockEvent blockEvent : getBlockEvents() ) { + + processBlockEventDetails( player, eventType, chance, blockEvent ); + } + + } + } + } + + private void processBlockEventDetails( Player player, BlockEventType eventType, double chance, MineBlockEvent blockEvent ) + { + if ( blockEvent.getEventType() == BlockEventType.eventTypeAll || + blockEvent.getEventType() == eventType ) { + + // If perms are set, check them, otherwise ignore perm check: + String perms = blockEvent.getPermission(); + if ( perms != null && perms.trim().length() > 0 && player.hasPermission( perms ) || + perms == null || + perms.trim().length() == 0 + ) { + + if ( chance <= blockEvent.getChance() ) { + + String formatted = blockEvent.getCommand(). + replace("{player}", player.getName()) + .replace("{player_uid}", player.getUUID().toString()); + + // Split multiple commands in to a List of indivual tasks: + List tasks = new ArrayList<>( + Arrays.asList( formatted.split( ";" ) )); + + + if ( tasks.size() > 0 ) { + + String errorMessage = "BlockEvent: Player: " + player.getName(); + + PrisonDispatchCommandTask task = + new PrisonDispatchCommandTask( tasks, errorMessage ); + + + switch ( blockEvent.getMode() ) + { + case "inline": + // Don't submit, but run it here within this thread: + task.run(); + break; + + case "sync": + case "async": // async will cause failures so run as sync: + + // submit task: + @SuppressWarnings( "unused" ) + int taskId = PrisonTaskSubmitter.runTaskLater(task, 0); + break; + + default: + break; + } + + } + + +// PrisonAPI.dispatchCommand(formatted); + } + } + } + } + public boolean checkZeroBlockReset() { boolean reset = false; // Reset if the mine runs out of blocks: - if ( !isVirtual() && - getRemainingBlockCount() == 0 && !isZeroBlockResetDisabled() || + + if ( !isVirtual() && ( + getRemainingBlockCount() <= 0 && !isZeroBlockResetDisabled() || getResetThresholdPercent() > 0 && getRemainingBlockCount() < (getBounds().getTotalBlockCount() * - getResetThresholdPercent() / 100.0d)) { + getResetThresholdPercent() / 100.0d) + )) { // submit a manual reset since the mine is empty: manualReset( MineResetType.NORMAL, getZeroBlockResetDelaySec() ); @@ -491,7 +585,7 @@ private void manualReset( MineResetType resetType, double delayActionSec ) { // cancel existing job: if ( getTaskId() != null ) { - Prison.get().getPlatform().getScheduler().cancelTask( getTaskId() ); + PrisonTaskSubmitter.cancelTask( getTaskId() ); } // Clear jobStack and set currentJob to run the RESET with zero delay: diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountAsyncTask.java index 3f725b52e..5da659e99 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountAsyncTask.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.mines.data; +import tech.mcprison.prison.tasks.PrisonRunnable; + public class OnStartupRefreshBlockBreakCountAsyncTask implements PrisonRunnable { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonDispatchCommandTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonDispatchCommandTask.java new file mode 100644 index 000000000..eb63490fa --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonDispatchCommandTask.java @@ -0,0 +1,38 @@ +package tech.mcprison.prison.mines.data; + +import java.util.List; + +import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.tasks.PrisonRunnable; + +public class PrisonDispatchCommandTask + implements PrisonRunnable { + + private List tasks; + private String errorMessage; + + public PrisonDispatchCommandTask( List tasks, String errorMessage ) { + this.tasks = tasks; + this.errorMessage = errorMessage; + } + + @Override + public void run() { + if ( tasks != null && tasks.size() > 0 ) { + + for ( String task : tasks ) { + + try { + PrisonAPI.dispatchCommand( task ); + } + catch ( Exception e ) { + + Output.get().logError( "PrisonDispatchCommand: Error trying to run task: " + errorMessage + + " Task: [" + task + "] " + e.getMessage() ); + } + } + + } + } +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonRunnable.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonRunnable.java deleted file mode 100644 index de33e22a8..000000000 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/PrisonRunnable.java +++ /dev/null @@ -1,7 +0,0 @@ -package tech.mcprison.prison.mines.data; - -public interface PrisonRunnable - extends Runnable -{ - -} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java new file mode 100644 index 000000000..fab0b0aad --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java @@ -0,0 +1,137 @@ +package tech.mcprison.prison.mines.features; + +import java.text.DecimalFormat; + +public class MineBlockEvent { + + private double chance; + private String permission; + private String command; + private String mode; + + private BlockEventType eventType; + + + public enum BlockEventType { + eventTypeAll, + eventBlockBreak, + eventTEXplosion; + + public static BlockEventType fromString( String type ) { + BlockEventType results = eventTypeAll; + + for ( BlockEventType eType : values() ) { + if ( eType.name().equalsIgnoreCase( type ) ) { + results = eType; + break; + } + } + + return results; + } + } + + public MineBlockEvent( double chance, String permission, + String command, String mode, BlockEventType eventType ) { + super(); + + this.chance = chance; + this.permission = permission; + this.command = command; + this.mode = mode; + + this.eventType = eventType; + } + + + public String toSaveString() { + DecimalFormat dFmt = new DecimalFormat("0.00000"); + return dFmt.format( getChance() ) + "|" + + (getPermission() == null || getPermission().trim().length() == 0 ? + "none" : getPermission()) + "|" + + getCommand() + "|" + getMode() + "|" + getEventType().name(); + } + + public static MineBlockEvent fromSaveString( String chancePermCommand ) { + MineBlockEvent results = null; + + if ( chancePermCommand != null && chancePermCommand.trim().length() > 0 ) { + String[] cpc = chancePermCommand.split( "\\|" ); + + double chance = cpc.length >= 1 ? Double.parseDouble( cpc[0] ) : 0d; + + String permission = cpc.length >= 2 ? cpc[1] : ""; + if ( permission == null || "none".equalsIgnoreCase( permission) ) { + permission = ""; + } + + String command = cpc.length >= 3 ? cpc[2] : ""; + + String mode = cpc.length >= 4 ? cpc[3] : "inline"; + + if ( !"sync".equalsIgnoreCase( mode ) && !"inline".equalsIgnoreCase( mode ) ) { + mode = "sync"; + } +// boolean async = (asyncStr != null && +// "true".equalsIgnoreCase( asyncStr ) ); + + BlockEventType eventType = cpc.length >= 5 ? BlockEventType.fromString( cpc[4] ) : + BlockEventType.eventTypeAll; + + if ( command != null && command.trim().length() > 0 ) { + + results = new MineBlockEvent( chance, permission, command, mode, eventType ); + } + } + + return results; + } + + + public double getChance() { + return chance; + } + public void setChance( double chance ) { + this.chance = chance; + } + + public String getPermission() { + return permission; + } + public void setPermission( String permission ) { + this.permission = permission; + } + + public String getCommand() { + return command; + } + public void setCommand( String command ) { + this.command = command; + } + + public String getMode() { + return mode; + } + public void setMode( String mode ) { + this.mode = mode; + } + + public BlockEventType getEventType() { + return eventType; + } + public void setEventType( BlockEventType eventType ) { + this.eventType = eventType; + } + + + public boolean isInline() { + return "inline".equalsIgnoreCase( getMode() ); + } + public boolean isSync() { + return "sync".equalsIgnoreCase( getMode() ); + } + public boolean isAsync() { + return "async".equalsIgnoreCase( getMode() ); + } + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLinerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java similarity index 98% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLinerBuilder.java rename to prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java index b92f5e580..6b9c76add 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLinerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.mines.data; +package tech.mcprison.prison.mines.features; import java.util.ArrayList; import java.util.List; @@ -8,6 +8,7 @@ import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Bounds; @@ -35,7 +36,8 @@ public enum LinerPatterns { blackAndWhite, seaEchos, - obby, + obby, + bedrock, glowingPlanks, darkOakPrismarine, beacon, @@ -555,6 +557,15 @@ private void select2DPattern( Edges edge ) { break; + case bedrock: + String[][] bedrock = + { + { "bedrock" } + }; + pattern2d = bedrock; + break; + + case glowingPlanks: String[][] glowingPlanks = { @@ -612,9 +623,9 @@ private void select2DPattern( Edges edge ) { { "end_stone", "glowstone" }, { "iron_block", "end_stone" }, - { "chiseled_quartz_block", "pillar_quartz_block" }, + { "chiseled_quartz_block", "quartz_pillar" }, { "glowstone", "quartz_block" }, - { "chiseled_quartz_block", "pillar_quartz_block" } + { "chiseled_quartz_block", "quartz_pillar" } }; pattern2d = bright; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerData.java new file mode 100644 index 000000000..98c40f3cb --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerData.java @@ -0,0 +1,385 @@ +package tech.mcprison.prison.mines.features; + +import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; +import tech.mcprison.prison.util.Bounds.Edges; + +public class MineLinerData { + + private String north; + private String east; + private String south; + private String west; + + private String walls; + + private String top; + private String bottom; + + private boolean forceNorth; + private boolean forceEast; + private boolean forceSouth; + private boolean forceWest; + + private boolean forceWalls; + + private boolean forceTop; + private boolean forceBottom; + + public MineLinerData() { + super(); + + this.north = null; + this.east = null; + this.south = null; + this.west = null; + + this.walls = null; + + this.top = null; + this.bottom = null; + + + this.forceNorth = false; + this.forceEast = false; + this.forceSouth = false; + this.forceWest = false; + + this.forceWalls = false; + + this.forceTop = false; + this.forceBottom = false; + } + + public MineLinerData( String walls, String bottom ) { + this(); + + this.walls = walls; + this.bottom = bottom; + } + + public MineLinerData( String north, String east, String south, String west, String bottom ) { + this(); + + this.north = north; + this.east = east; + this.south = south; + this.west = west; + + this.bottom = bottom; + } + + public String toInfoString() { + String results = generateStringValue(" &2", " &7"); + + if ( results.trim().isEmpty() ) { + results = "&dNone"; + } + + return results; + } + + public String toSaveString() { + return generateStringValue("", ""); + } + + private String generateStringValue( String color1, String color2 ) { + + StringBuilder sb = new StringBuilder(); + + addSaveString( sb, Edges.north, getNorth(), isForceNorth(), color1, color2 ); + addSaveString( sb, Edges.east, getEast(), isForceEast(), color1, color2 ); + addSaveString( sb, Edges.south, getSouth(), isForceSouth(), color1, color2 ); + addSaveString( sb, Edges.west, getWest(), isForceWest(), color1, color2 ); + + addSaveString( sb, Edges.walls, getWalls(), isForceWalls(), color1, color2 ); + + addSaveString( sb, Edges.top, getTop(), isForceTop(), color1, color2 ); + addSaveString( sb, Edges.bottom, getBottom(), isForceBottom(), color1, color2 ); + + return sb.toString(); + } + + /** + *

This is an internal function that builds this object as a String so it can be saved and + * restored. The format it generates is edge-colon-value and if there are more than one, then + * it will insert a comma with no spaces. + *

+ * + * @param sb + * @param edge + * @param value + */ + private void addSaveString( StringBuilder sb, Edges edge, String value, + boolean forced, + String color1, String color2 ) { + if ( value != null && value.trim().length() > 0 ) { + if ( sb.length() > 0 ) { + sb.append( "," ); + } + + sb.append( color1 ).append( edge.name() ).append( ":" ) + .append( color2 ).append( value ); + if ( forced ) { + sb.append( ":" ).append( color2 ).append( "forced" ); + } + } + } + + public static MineLinerData fromSaveString( String savedLiner ) { + MineLinerData results = new MineLinerData(); + + if ( savedLiner != null && savedLiner.trim().length() > 0 ) { + + String[] surfaces = savedLiner.split( "," ); + + for ( String surface : surfaces ) { + if ( surface != null && surface.indexOf( ':' ) != -1 ) { + String[] edgePatternName = surface.split( ":" ); + Edges edge = Edges.fromString( edgePatternName[0] ); + String pattern = edgePatternName[1]; + boolean forced = edgePatternName.length > 2 && + "forced".equalsIgnoreCase( edgePatternName[2] ); + + results.setLiner( edge, pattern, forced ); + } + } + } + + return results; + } + + private void setLiner( Edges edge, String pattern, boolean forced ) { + switch ( edge ) + { + case north: + setNorth( pattern ); + setForceNorth( forced ); + break; + + case east: + setEast( pattern ); + setForceEast( forced ); + break; + + case south: + setSouth( pattern ); + setForceSouth( forced ); + break; + + case west: + setWest( pattern ); + setForceWest( forced ); + break; + + case walls: + setWalls( pattern ); + setForceWalls( forced ); + break; + + case top: + setTop( pattern ); + setForceTop( forced ); + break; + + case bottom: + setBottom( pattern ); + setForceBottom( forced ); + break; + + default: + break; + } + } + + + + public void setLiner( Edges edge, LinerPatterns linerPattern, boolean isForced ) { + + setLiner( edge, linerPattern.name(), isForced ); + } + + public boolean hasEdge( Edges edge ) { + + return getEdge( edge ) != null; + } + + public String getEdge( Edges edge ) { + String results = null; + + switch ( edge ) + { + case north: + results = getNorth() != null ? getNorth() : getWalls(); + break; + + case east: + results = getEast() != null ? getEast() : getWalls(); + break; + + case south: + results = getSouth() != null ? getSouth() : getWalls(); + break; + + case west: + results = getWest() != null ? getWest() : getWalls(); + break; + + case walls: + results = getWalls(); + break; + + case top: + results = getTop(); + break; + + case bottom: + results = getBottom(); + break; + + default: + break; + } + + return results; + } + + public boolean getForce( Edges edge ) { + boolean results = false; + + switch ( edge ) + { + case north: + results = isForceNorth() || isForceWalls(); + break; + + case east: + results = isForceEast() || isForceWalls(); + break; + + case south: + results = isForceSouth() || isForceWalls(); + break; + + case west: + results = isForceWest() || isForceWalls(); + break; + + case walls: + results = isForceWalls(); + break; + + case top: + results = isForceTop(); + break; + + case bottom: + results = isForceBottom(); + break; + + default: + break; + } + return results; + } + + public String getNorth() { + return north; + } + public void setNorth( String north ) { + this.north = north; + } + + public String getEast() { + return east; + } + public void setEast( String east ) { + this.east = east; + } + + public String getSouth() { + return south; + } + public void setSouth( String south ) { + this.south = south; + } + + public String getWest() { + return west; + } + public void setWest( String west ) { + this.west = west; + } + + public String getWalls() { + return walls; + } + public void setWalls( String walls ) { + this.walls = walls; + } + + public String getTop() { + return top; + } + public void setTop( String top ) { + this.top = top; + } + + public String getBottom() { + return bottom; + } + public void setBottom( String bottom ) { + this.bottom = bottom; + } + + public boolean isForceNorth() { + return forceNorth; + } + public void setForceNorth( boolean forceNorth ) { + this.forceNorth = forceNorth; + } + + public boolean isForceEast() { + return forceEast; + } + public void setForceEast( boolean forceEast ) { + this.forceEast = forceEast; + } + + public boolean isForceSouth() { + return forceSouth; + } + public void setForceSouth( boolean forceSouth ) { + this.forceSouth = forceSouth; + } + + public boolean isForceWest() { + return forceWest; + } + public void setForceWest( boolean forceWest ) { + this.forceWest = forceWest; + } + + public boolean isForceWalls() { + return forceWalls; + } + public void setForceWalls( boolean forceWalls ) { + this.forceWalls = forceWalls; + } + + public boolean isForceTop() { + return forceTop; + } + public void setForceTop( boolean forceTop ) { + this.forceTop = forceTop; + } + + public boolean isForceBottom() { + return forceBottom; + } + public void setForceBottom( boolean forceBottom ) { + this.forceBottom = forceBottom; + } + + + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineMover.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java similarity index 81% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineMover.java rename to prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java index 10898d3e3..d5dcee4b5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineMover.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java @@ -1,6 +1,7 @@ -package tech.mcprison.prison.mines.data; +package tech.mcprison.prison.mines.features; -import tech.mcprison.prison.mines.data.MineLinerBuilder.LinerPatterns; +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.util.Bounds; import tech.mcprison.prison.util.Bounds.Edges; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlock.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlock.java similarity index 83% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlock.java rename to prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlock.java index 6753b79c5..3ced612c5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlock.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlock.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.mines.data; +package tech.mcprison.prison.mines.features; import tech.mcprison.prison.util.BlockType; @@ -8,10 +8,14 @@ public class MineTargetBlock private BlockType blockType; - public MineTargetBlock( BlockType blockType, int x, int y, int z ) { - super(); + protected MineTargetBlock( int x, int y, int z ) { this.blockKey = new MineTargetBlockKey( x, y, z ); + } + + public MineTargetBlock( BlockType blockType, int x, int y, int z ) { + this( x, y, z ); + this.blockType = blockType; } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlockKey.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java similarity index 93% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlockKey.java rename to prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java index 2c55e1308..12b1e76be 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTargetBlockKey.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.mines.data; +package tech.mcprison.prison.mines.features; public class MineTargetBlockKey implements Comparable diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java new file mode 100644 index 000000000..ea7cbaf03 --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java @@ -0,0 +1,25 @@ +package tech.mcprison.prison.mines.features; + +import tech.mcprison.prison.internal.block.PrisonBlock; + +public class MineTargetPrisonBlock + extends MineTargetBlock +{ + private PrisonBlock prisonBlock; + + public MineTargetPrisonBlock( PrisonBlock prisonBlock, int x, int y, int z ) { + super( x, y, z ); + + this.prisonBlock = prisonBlock; + } + + public PrisonBlock getPrisonBlock() + { + return prisonBlock; + } + public void setPrisonBlock( PrisonBlock prisonBlock ) + { + this.prisonBlock = prisonBlock; + } + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTracerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java similarity index 97% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTracerBuilder.java rename to prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java index 810abbffb..d2d98ad8e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTracerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java @@ -1,10 +1,11 @@ -package tech.mcprison.prison.mines.data; +package tech.mcprison.prison.mines.features; import java.util.Optional; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Location; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java index faa6b6bba..a7aebbbfb 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java @@ -26,11 +26,11 @@ import java.util.UUID; import tech.mcprison.prison.Prison; -import tech.mcprison.prison.integration.IntegrationManager; -import tech.mcprison.prison.integration.IntegrationManager.PlaceHolderFlags; -import tech.mcprison.prison.integration.IntegrationManager.PrisonPlaceHolders; import tech.mcprison.prison.integration.ManagerPlaceholders; import tech.mcprison.prison.integration.PlaceHolderKey; +import tech.mcprison.prison.integration.PlaceholderManager; +import tech.mcprison.prison.integration.PlaceholderManager.PlaceHolderFlags; +import tech.mcprison.prison.integration.PlaceholderManager.PrisonPlaceHolders; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.mines.PrisonMines; @@ -212,13 +212,16 @@ public void loadFromDbCollection( PrisonMines pMines ) { this.coll = collOptional.get(); - int offsetTiming = 5; - loadMines(offsetTiming); + + // Default value of 5 seconds: + long offsetTimingMs = Prison.get().getPlatform() + .getConfigInt( "prison-mines-reset-gap", 5000 ); + loadMines(offsetTimingMs); Output.get().logInfo( String.format("Loaded %d mines and submitted with a %d " + - "second offset timing for auto resets.", - getMines().size(), offsetTiming)); + "millisecond offset timing for auto resets.", + getMines().size(), offsetTimingMs)); // // When finished loading the mines, then if there are any worlds that @@ -265,9 +268,10 @@ public boolean add(Mine mine) { * @param mine the mine instance * @param save - bypass the option to save. Useful for when initially loading the mines since * no data has changed. + * @param offsetTiming in milliseconds * @return if the add was successful */ - private boolean add(Mine mine, boolean save, int offsetTiming ) { + private boolean add(Mine mine, boolean save, int offsetTimingMs ) { boolean results = false; if (!getMines().contains(mine)){ if ( save ) { @@ -278,7 +282,7 @@ private boolean add(Mine mine, boolean save, int offsetTiming ) { getMinesByName().put( mine.getName().toLowerCase(), mine ); // Start its scheduling: - mine.submit(offsetTiming); + mine.submit( offsetTimingMs / 1000d ); } return results; } @@ -308,15 +312,15 @@ public boolean removeMine(Mine mine) { - private void loadMines( int offsetTiming ) { + private void loadMines( long offsetTimingMs ) { List mineDocuments = coll.getAll(); - int offset = 0; + int offsetMs = 0; for (Document document : mineDocuments) { try { Mine m = new Mine(document); - add(m, false, offset); - offset += offsetTiming; + add(m, false, offsetMs); + offsetMs += offsetTimingMs; } catch (Exception e) { Output.get() @@ -540,8 +544,8 @@ public String getTranslateMinesPlaceHolder( String identifier ) { String results = null; List placeHolderKeys = getTranslatedPlaceHolderKeys(); - if ( !identifier.startsWith( IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { - identifier = IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; + if ( !identifier.startsWith( PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { + identifier = PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; } for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { @@ -654,7 +658,7 @@ private String getTranslateMinesPlaceHolder( PlaceHolderKey placeHolderKey, Mine int totalBlocks = mine.getBounds().getTotalBlockCount(); int blocksRemaining = mine.getRemainingBlockCount(); - results = Prison.get().getIntegrationManager(). + results = Prison.get().getPlaceholderManager(). getProgressBar( ((double) blocksRemaining), ((double) totalBlocks), false ); break; @@ -705,8 +709,8 @@ public String getTranslatePlayerMinesPlaceHolder( UUID playerUuid, String player List placeHolderKeys = getTranslatedPlaceHolderKeys(); - if ( !identifier.startsWith( IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { - identifier = IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; + if ( !identifier.startsWith( PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { + identifier = PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; } for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { @@ -787,7 +791,7 @@ private String getRemainingTimeBar( Mine mine ) { double timeRemaining = mine.getRemainingTimeSec(); int time = mine.getResetTime(); - return Prison.get().getIntegrationManager(). + return Prison.get().getPlaceholderManager(). getProgressBar( timeRemaining, ((double) time), true ); } @@ -817,13 +821,13 @@ public List getTranslatedPlaceHolderKeys() { for ( Mine mine : getMines() ) { for ( PrisonPlaceHolders ph : placeHolders ) { String key = ph.name().replace( - IntegrationManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). + PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). toLowerCase(); PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, mine.getName() ); if ( ph.getAlias() != null ) { String aliasName = ph.getAlias().name().replace( - IntegrationManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). + PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). toLowerCase(); placeholder.setAliasName( aliasName ); } diff --git a/prison-mines/src/test/java/tech/mcprison/prison/mines/data/MineLinerBuilderTest.java b/prison-mines/src/test/java/tech/mcprison/prison/mines/data/MineLinerBuilderTest.java index 6518f47fd..1d746c79c 100644 --- a/prison-mines/src/test/java/tech/mcprison/prison/mines/data/MineLinerBuilderTest.java +++ b/prison-mines/src/test/java/tech/mcprison/prison/mines/data/MineLinerBuilderTest.java @@ -4,6 +4,7 @@ import org.junit.Test; +import tech.mcprison.prison.mines.features.MineLinerBuilder; import tech.mcprison.prison.util.Bounds.Edges; public class MineLinerBuilderTest diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java index af8cf5e41..045b4978f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java @@ -41,7 +41,9 @@ /** * @author Faizaan A. Datoo */ -public class PrisonRanks extends Module { +public class PrisonRanks + extends Module { + public static final String MODULE_NAME = "Ranks"; /* * Fields & Constants @@ -76,7 +78,8 @@ public static PrisonRanks getInstance() { return instance; } - @Override public void enable() { + @Override + public void enable() { instance = this; if (!PrisonAPI.getIntegrationManager().hasForType(IntegrationType.ECONOMY)) { @@ -178,7 +181,32 @@ public static PrisonRanks getInstance() { } - private Collection initCollection(String collName) { + + /** + * This function deferredStartup() will be called after the integrations have been + * loaded. + * + */ + @Override + public void deferredStartup() { + } + + /** + *

Do not save ranks upon server shutdown or plugin disable events. The + * ranks should be saved every time there is a modification to them. + *

+ */ + @Override + public void disable() { +// try { +// rankManager.saveRanks(); +// } catch (IOException e) { +// Output.get().logError("A ranks file failed to save.", e); +// } + } + + + private Collection initCollection(String collName) { Optional collectionOptional = database.getCollection(collName); if (!collectionOptional.isPresent()) { database.createCollection(collName); @@ -236,19 +264,7 @@ private void createDefaultLadder() { * Getters & Setters */ - /** - *

Do not save ranks upon server shutdown or plugin disable events. The - * ranks should be saved every time there is a modification to them. - *

- */ - @Override - public void disable() { -// try { -// rankManager.saveRanks(); -// } catch (IOException e) { -// Output.get().logError("A ranks file failed to save.", e); -// } - } + public RankManager getRankManager() { return rankManager; diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java index f71796bb3..73c750122 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java @@ -57,15 +57,26 @@ public enum RankupModes { public enum RankupStatus { RANKUP_SUCCESS, RANKUP_FAILURE, + RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER, + RANKUP_FAILURE_COULD_NOT_LOAD_LADDER, + RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, + RANKUP_FAILURE_COULD_NOT_SAVE_PLAYER_FILE, + RANKUP_FAILURE_RANK_DOES_NOT_EXIST, RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER, RANKUP_FAILURE_CURRENCY_IS_NOT_SUPPORTED, + RANKUP_EVENT_CANCELED, + RANKUP_LOWEST, RANKUP_HIGHEST, RANKUP_CANT_AFFORD, RANKUP_NO_RANKS, + RANKUP_LADDER_REMOVED, + RANKUP_FAILURE_REMOVING_LADDER, + + IN_PROGRESS ; } @@ -116,6 +127,14 @@ public enum RankupTransactions { player_balance_final, zero_cost_to_player, + attempting_to_delete_ladder_from_player, + cannot_delete_default_ladder, + ladder_was_removed_from_player, + could_not_delete_ladder, + + failed_rankup_event_canceled_outside_of_prison, + + failure_cannot_save_player_file, rankupCommandsStart, @@ -155,26 +174,26 @@ public RankUtil() { - public RankupResults rankupPlayer(RankPlayer player, String ladderName, String playerName) { - return rankupPlayer(RankupCommands.rankup, player, ladderName, null, + public RankupResults rankupPlayer(Player player, RankPlayer rankPlayer, String ladderName, String playerName) { + return rankupPlayer(RankupCommands.rankup, player, rankPlayer, ladderName, null, playerName, null, PromoteForceCharge.charge_player ); } - public RankupResults promotePlayer(RankPlayer player, String ladderName, + public RankupResults promotePlayer(Player player, RankPlayer rankPlayer, String ladderName, String playerName, String executorName, PromoteForceCharge pForceCharge) { - return rankupPlayer(RankupCommands.promote, player, ladderName, null, + return rankupPlayer(RankupCommands.promote, player, rankPlayer, ladderName, null, playerName, executorName, pForceCharge); } - public RankupResults demotePlayer(RankPlayer player, String ladderName, + public RankupResults demotePlayer(Player player, RankPlayer rankPlayer, String ladderName, String playerName, String executorName, PromoteForceCharge pForceCharge) { - return rankupPlayer(RankupCommands.demote, player, ladderName, null, + return rankupPlayer(RankupCommands.demote, player, rankPlayer, ladderName, null, playerName, executorName, pForceCharge); } - public RankupResults setRank(RankPlayer player, String ladderName, String rankName, + public RankupResults setRank(Player player, RankPlayer rankPlayer, String ladderName, String rankName, String playerName, String executorName) { - return rankupPlayer(RankupCommands.setrank, player, ladderName, rankName, + return rankupPlayer(RankupCommands.setrank, player, rankPlayer, ladderName, rankName, playerName, executorName, PromoteForceCharge.no_charge ); } @@ -193,7 +212,7 @@ public RankupResults setRank(RankPlayer player, String ladderName, String rankNa * @param executorName * @return */ - private RankupResults rankupPlayer(RankupCommands command, RankPlayer player, String ladderName, + private RankupResults rankupPlayer(RankupCommands command, Player player, RankPlayer rankPlayer, String ladderName, String rankName, String playerName, String executorName, PromoteForceCharge pForceCharge ) { @@ -238,9 +257,25 @@ private RankupResults rankupPlayer(RankupCommands command, RankPlayer player, St break; } + + +// Player prisonPlayer = rankPlayer; +// Player prisonPlayer = PrisonAPI.getPlayer(player.uid).orElse(null); + if( player == null ) { + results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER, RankupTransactions.failed_player ); + return results; + } + + + // If ladderName is null, then assign it the default ladder: + if ( ladderName == null ) { + ladderName = "default"; + results.addTransaction(RankupTransactions.assigned_default_ladder); + } + try { - rankupPlayerInternal(results, command, player, ladderName, + rankupPlayerInternal(results, command, player, rankPlayer, ladderName, rankName, playerName, executorName, pForceCharge ); } catch (Exception e ) { results.addTransaction( RankupTransactions.failure_exception_caught_check_server_logs ); @@ -264,150 +299,100 @@ private RankupResults rankupPlayer(RankupCommands command, RankPlayer player, St * @param ladderName The name of the ladder to rank up this player on. */ private void rankupPlayerInternal(RankupResults results, - RankupCommands command, RankPlayer player, String ladderName, + RankupCommands command, Player prisonPlayer, RankPlayer rankPlayer, String ladderName, String rankName, String playerName, String executorName, PromoteForceCharge pForceCharge) { + - - Player prisonPlayer = PrisonAPI.getPlayer(player.uid).orElse(null); - if( prisonPlayer == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE, RankupTransactions.failed_player ); - return; - } - - // If ladderName is null, then assign it the default ladder: - if ( ladderName == null ) { - ladderName = "default"; - results.addTransaction(RankupTransactions.assigned_default_ladder); - } + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName).orElse(null); if( ladder == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE, RankupTransactions.failed_ladder ); + results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_LADDER, RankupTransactions.failed_ladder ); return; } - Optional currentRankOptional = player.getRank(ladder); - Rank originalRank = currentRankOptional.orElse( null ); + Rank originalRank = rankPlayer.getRank(ladder.name); +// Optional currentRankOptional = player.getRank(ladder); +// Rank originalRank = currentRankOptional.orElse( null ); results.addTransaction( RankupTransactions.orginal_rank ); results.setOriginalRank( originalRank ); - Rank targetRank = null; + /** + * calculate the target rank: + */ + Rank targetRank = calculateTargetRank( command, results, originalRank, ladder, + ladderName, rankName ); - // For all commands except for setrank, if the player does not have a current rank, then - // set it to the default and skip all other rank processing: - - if (!currentRankOptional.isPresent() && - ( command == RankupCommands.rankup || - command == RankupCommands.promote || - command == RankupCommands.demote )) { - // Set the default rank: - Optional lowestRank = ladder.getByPosition(0); - if (!lowestRank.isPresent()) { - results.addTransaction( RankupStatus.RANKUP_NO_RANKS, - RankupTransactions.no_ranks_found_on_ladder ); - return; - } - results.addTransaction( RankupTransactions.set_to_default_rank ); - targetRank = lowestRank.get(); - - // need to set this to a valid value: - originalRank = lowestRank.get(); + if ( results.getStatus() != RankupStatus.IN_PROGRESS ) { + // Failed while calculatingTargetRank so return now: + return; } - if ( originalRank == null ) { - results.addTransaction( RankupTransactions.original_rank_is_null ); - - } - // If default ladder and rank is null at this point, that means use the "default" rank: - if ( command == RankupCommands.setrank ) { - - if ("default".equalsIgnoreCase( ladderName ) && rankName == null ) { - Optional lowestRank = ladder.getLowestRank(); - if ( lowestRank.isPresent() ) { - targetRank = lowestRank.get(); - rankName = targetRank.name; - - results.addTransaction(RankupTransactions.assigned_default_rank); - } - - } + // Process the remove rank request + if ( command == RankupCommands.setrank && "-remove-".equalsIgnoreCase( rankName ) ) { + results.addTransaction(RankupTransactions.attempting_to_delete_ladder_from_player); - if ( targetRank == null && rankName != null ) { - - targetRank = PrisonRanks.getInstance().getRankManager().getRank( rankName ); - - if ( targetRank != null ) { - - if ( !ladder.containsRank( targetRank.id )) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER, - RankupTransactions.failed_rank_not_in_ladder ); - return; - } - } else { - results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, - RankupTransactions.failed_rank_not_found ); - return; - } - } else { - results.addTransaction( RankupTransactions.failed_setrank ); - - // Got a problem... if using setrank and no rankName is provided, this is a problem - // But it should never get this far if that is the situation + if ("default".equalsIgnoreCase( ladderName ) ) { + results.addTransaction(RankupTransactions.cannot_delete_default_ladder); } - } - - if ( targetRank == null ) { - - Optional nextRankOptional = null; - if ( command == RankupCommands.rankup || command == RankupCommands.promote ) { - // Trying to promote: - nextRankOptional = ladder.getNext(ladder.getPositionOfRank(currentRankOptional.get())); - - if (!nextRankOptional.isPresent()) { - // We're already at the highest rank. - results.addTransaction( RankupStatus.RANKUP_HIGHEST, - RankupTransactions.no_higher_rank_found ); - return; - } - targetRank = nextRankOptional.get(); - results.addTransaction( RankupTransactions.set_to_next_higher_rank ); - - } else if ( command == RankupCommands.demote ) { - // Trying to demote: - nextRankOptional = ladder.getPrevious(ladder.getPositionOfRank(currentRankOptional.get())); + else { + boolean success = rankPlayer.removeLadder( ladder.name ); - if (!nextRankOptional.isPresent()) { - // We're already at the lowest rank. - results.addTransaction( RankupStatus.RANKUP_LOWEST, - RankupTransactions.no_lower_rank_found ); + if ( success ) { + results.addTransaction( RankupStatus.RANKUP_LADDER_REMOVED, + RankupTransactions.ladder_was_removed_from_player ); return; } - targetRank = nextRankOptional.get(); - results.addTransaction( RankupTransactions.set_to_prior_lower_rank ); } + + results.addTransaction( RankupStatus.RANKUP_FAILURE_REMOVING_LADDER, + RankupTransactions.could_not_delete_ladder ); + + return; } + + // Target rank is still null, so something failed so terminate: if ( targetRank == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE, RankupTransactions.failed_unable_to_assign_rank ); + results.addTransaction( RankupStatus.RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, RankupTransactions.failed_unable_to_assign_rank ); return; } - results.setTargetRank( targetRank ); + + + + double nextRankCost = targetRank.cost; + double currentRankCost = (originalRank == null ? 0 : originalRank.cost); + + + results.addTransaction( RankupTransactions.fireRankupEvent ); + + // Nothing can cancel a RankUpEvent: + RankUpEvent rankupEvent = new RankUpEvent(rankPlayer, originalRank, targetRank, nextRankCost, + command, pForceCharge ); + Prison.get().getEventBus().post(rankupEvent); + + if ( rankupEvent.isCanceled() ) { + + + results.addTransaction( RankupStatus.RANKUP_EVENT_CANCELED, + RankupTransactions.failed_rankup_event_canceled_outside_of_prison ); + return; + + } // We're going to be making a transaction here // We'll check if the player can afford it first, and if so, we'll make the transaction and proceed. - - double nextRankCost = targetRank.cost; - double currentRankCost = (originalRank == null ? 0 : originalRank.cost); + if (pForceCharge != PromoteForceCharge.no_charge ) { @@ -491,14 +476,14 @@ private void rankupPlayerInternal(RankupResults results, results.addTransaction( RankupTransactions.zero_cost_to_player ); } - player.addRank(ladder, targetRank); + rankPlayer.addRank(ladder, targetRank); try { - PrisonRanks.getInstance().getPlayerManager().savePlayer(player); + PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); } catch (IOException e) { Output.get().logError("An error occurred while saving player files.", e); - results.addTransaction( RankupStatus.RANKUP_FAILURE, + results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_SAVE_PLAYER_FILE, RankupTransactions.failure_cannot_save_player_file ); return; } @@ -510,24 +495,148 @@ private void rankupPlayerInternal(RankupResults results, int count = 0; for (String cmd : targetRank.rankUpCommands) { - String formatted = cmd.replace("{player}", prisonPlayer.getName()) - .replace("{player_uid}", player.uid.toString()); - PrisonAPI.dispatchCommand(formatted); - count++; + if ( cmd != null ) { + + String formatted = cmd.replace("{player}", prisonPlayer.getName()) + .replace("{player_uid}", rankPlayer.uid.toString()); + +// Prison.get().getPlatform().logPlain( +// String.format( "RankUtil.rankupPlayerInternal: Rank Command: [%s]", +// formatted )); + + PrisonAPI.dispatchCommand(formatted); + count++; + } } results.setRankupCommandsExecuted( count ); results.addTransaction( RankupTransactions.rankupCommandsCompleted ); - results.addTransaction( RankupTransactions.fireRankupEvent ); - Prison.get().getEventBus().post( - new RankUpEvent(player, currentRankOptional.orElse(null), targetRank, nextRankCost)); +// results.addTransaction( RankupTransactions.fireRankupEvent ); +// +// // Nothing can cancel a RankUpEvent: +// RankUpEvent rankupEvent = new RankUpEvent(rankPlayer, originalRank, targetRank, nextRankCost); +// Prison.get().getEventBus().post(rankupEvent); results.addTransaction( RankupStatus.RANKUP_SUCCESS, RankupTransactions.rankup_successful ); } + + private Rank calculateTargetRank(RankupCommands command, RankupResults results, + Rank originalRank, RankLadder ladder, String ladderName, String rankName ) { + Rank targetRank = null; + + + // For all commands except for setrank, if the player does not have a current rank, then + // set it to the default and skip all other rank processing: + + if ( originalRank == null && + ( command == RankupCommands.rankup || + command == RankupCommands.promote || + command == RankupCommands.demote )) { + // Set the default rank: + Optional lowestRank = ladder.getByPosition(0); + if (!lowestRank.isPresent()) { + results.addTransaction( RankupStatus.RANKUP_NO_RANKS, + RankupTransactions.no_ranks_found_on_ladder ); + return targetRank; + } + results.addTransaction( RankupTransactions.set_to_default_rank ); + targetRank = lowestRank.get(); + + // need to set this to a valid value: + originalRank = lowestRank.get(); + } + + if ( originalRank == null ) { + results.addTransaction( RankupTransactions.original_rank_is_null ); + + } + + + + // If default ladder and rank is null at this point, that means use the "default" rank: + if ( command == RankupCommands.setrank ) { + + if ( "-remove-".equalsIgnoreCase( rankName ) ) { + + // process the -remove- rank after this function returns: + return targetRank; + } + + else if ("default".equalsIgnoreCase( ladderName ) && rankName == null ) { + Optional lowestRank = ladder.getLowestRank(); + if ( lowestRank.isPresent() ) { + targetRank = lowestRank.get(); + rankName = targetRank.name; + + results.addTransaction(RankupTransactions.assigned_default_rank); + } + + } + + if ( targetRank == null && rankName != null ) { + + targetRank = PrisonRanks.getInstance().getRankManager().getRank( rankName ); + + if ( targetRank != null ) { + + if ( !ladder.containsRank( targetRank.id )) { + results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER, + RankupTransactions.failed_rank_not_in_ladder ); + return targetRank; + } + } else { + results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, + RankupTransactions.failed_rank_not_found ); + return targetRank; + } + } else { + results.addTransaction( RankupTransactions.failed_setrank ); + + // Got a problem... if using setrank and no rankName is provided, this is a problem + // But it should never get this far if that is the situation + } + } + + + + if ( targetRank == null ) { + + if ( command == RankupCommands.rankup || command == RankupCommands.promote ) { + // Trying to promote: +// nextRankOptional = ladder.getNext(ladder.getPositionOfRank(currentRankOptional.get())); + + if ( originalRank.getRankNext() == null ) { + // We're already at the highest rank. + results.addTransaction( RankupStatus.RANKUP_HIGHEST, + RankupTransactions.no_higher_rank_found ); + return targetRank; + } + targetRank = originalRank.getRankNext(); + results.addTransaction( RankupTransactions.set_to_next_higher_rank ); + + } else if ( command == RankupCommands.demote ) { + // Trying to demote: +// nextRankOptional = ladder.getPrevious(ladder.getPositionOfRank(currentRankOptional.get())); + + if ( originalRank.getRankPrior() == null ) { + // We're already at the lowest rank. + results.addTransaction( RankupStatus.RANKUP_LOWEST, + RankupTransactions.no_lower_rank_found ); + return targetRank; + } + targetRank = originalRank.getRankPrior(); + results.addTransaction( RankupTransactions.set_to_prior_lower_rank ); + } + } + + return targetRank; + } + + public static String doubleToDollarString(double val) { return NumberFormat.getCurrencyInstance().format(val); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java index 19da1e5e3..8b3bfa56a 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java @@ -85,8 +85,11 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode // RETRIEVE THE LADDER // This player has to have permission to rank up on this ladder. - if (!ladder.equalsIgnoreCase("default") && !sender - .hasPermission(permission + ladder.toLowerCase())) { + if (!(ladder.equalsIgnoreCase("prestiges") && + (Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || + Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ))) && + !ladder.equalsIgnoreCase("default") && + !sender.hasPermission(permission + ladder.toLowerCase())) { Output.get() .sendError(sender, "You need the permission '%s' to rank up on this ladder.", permission + ladder.toLowerCase()); @@ -112,14 +115,15 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode return; } - RankPlayer rankPlayer = getPlayer( sender, player.getUUID(), player.getName() ); + RankPlayer rankPlayer = getRankPlayer( sender, player.getUUID(), player.getName() ); Rank pRank = rankPlayer.getRank( ladder ); - Rank pRankSecond = rankPlayer.getRank("default"); + // gets the rank on the default ladder. Used if ladder is not default. + Rank pRankSecond = rankPlayer.getRank("default"); Rank pRankAfter = null; LadderManager lm = PrisonRanks.getInstance().getLadderManager(); boolean willPrestige = false; - // If the ladder's the prestige one, it'll execute all of this + // If the player is trying to prestige, then the following must be ran to setup the prestige checks: if ( ladder!= null && ladder.equalsIgnoreCase("prestiges")) { if (!(lm.getLadder("default").isPresent())){ @@ -151,10 +155,13 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode boolean rankupWithSuccess = false; if ( ladder != null && rankPlayer != null ) { - RankupResults results = new RankUtil().rankupPlayer(rankPlayer, ladder, sender.getName()); + + // Performs the actual rankup here: + RankupResults results = new RankUtil().rankupPlayer(player, rankPlayer, ladder, sender.getName()); processResults( sender, null, results, true, null, ladder, currency ); + // If the last rankup attempt was successful and they are trying to rankup as many times as possible: if (results.getStatus() == RankupStatus.RANKUP_SUCCESS && mode == RankupModes.MAX_RANKS && !ladder.equals("prestiges")) { rankUpPrivate( sender, ladder, mode, permission ); @@ -189,10 +196,15 @@ private void prestigePlayer(Player player, RankPlayer rankPlayer, Rank pRank, Ra // Get economy EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); - if ( economy != null ) { + boolean resetBalance = Prison.get().getPlatform().getConfigBooleanTrue( "prestige.resetMoney" ); + + if ( economy != null || !resetBalance ) { - // Set the player balance to 0 (reset) - economy.setBalance(player, 0); + if ( resetBalance ) { + // Set the player balance to 0 (reset) + economy.setBalance(player, 0); + } + // Send a message to the player because he did prestige! player.sendMessage("&7[&3Congratulations&7] &3You've &6Prestige&3 to " + pRankAfter.tag + "&c!"); } @@ -233,7 +245,7 @@ public void promotePlayer(CommandSender sender, ladder = confirmLadder( sender, ladder ); - RankPlayer rankPlayer = getPlayer( sender, playerUuid, player.getName() ); + RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); Rank pRank = rankPlayer.getRank( ladder ); // Get currency if it exists, otherwise it will be null if the Rank has no currency: @@ -242,7 +254,7 @@ public void promotePlayer(CommandSender sender, if ( ladder != null && rankPlayer != null ) { - RankupResults results = new RankUtil().promotePlayer(rankPlayer, ladder, + RankupResults results = new RankUtil().promotePlayer(player, rankPlayer, ladder, player.getName(), sender.getName(), pForceCharge); processResults( sender, player, results, true, null, ladder, currency ); @@ -279,14 +291,14 @@ public void demotePlayer(CommandSender sender, ladder = confirmLadder( sender, ladder ); - RankPlayer rankPlayer = getPlayer( sender, playerUuid, player.getName() ); + RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); Rank pRank = rankPlayer.getRank( ladder ); // Get currency if it exists, otherwise it will be null if the Rank has no currency: String currency = rankPlayer == null || pRank == null ? null : pRank.currency; if ( ladder != null && rankPlayer != null ) { - RankupResults results = new RankUtil().demotePlayer(rankPlayer, ladder, + RankupResults results = new RankUtil().demotePlayer(player, rankPlayer, ladder, player.getName(), sender.getName(), pForceCharge); processResults( sender, player, results, false, null, ladder, currency ); @@ -298,7 +310,8 @@ public void demotePlayer(CommandSender sender, permissions = "ranks.setrank", onlyPlayers = false) public void setRank(CommandSender sender, @Arg(name = "playerName", def = "", description = "Player name") String playerName, - @Arg(name = "rankName", description = "The rank to assign to the player") String rank, + @Arg(name = "rankName", description = "The rank to assign to the player, or [-remove-] " + + "to deleete the player from the rank.") String rank, @Arg(name = "ladder", description = "The ladder to demote on.", def = "default") String ladder) { Player player = getPlayer( sender, playerName ); @@ -318,14 +331,14 @@ private void setPlayerRank( Player player, String rank, String ladder, CommandSe ladder = confirmLadder( sender, ladder ); - RankPlayer rankPlayer = getPlayer( sender, playerUuid, player.getName() ); + RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); Rank pRank = rankPlayer.getRank( ladder ); // Get currency if it exists, otherwise it will be null if the Rank has no currency: String currency = rankPlayer == null || pRank == null ? null : pRank.currency; if ( ladder != null && rankPlayer != null ) { - RankupResults results = new RankUtil().setRank(rankPlayer, ladder, rank, + RankupResults results = new RankUtil().setRank(player, rankPlayer, ladder, rank, player.getName(), sender.getName()); processResults( sender, player, results, true, rank, ladder, currency ); @@ -350,9 +363,10 @@ public String confirmLadder( CommandSender sender, String ladderName ) { } - public RankPlayer getPlayer( CommandSender sender, UUID playerUuid, String playerName ) { + public RankPlayer getRankPlayer( CommandSender sender, UUID playerUuid, String playerName ) { + Optional playerOptional = - PrisonRanks.getInstance().getPlayerManager().getPlayer(playerUuid, playerName); + PrisonRanks.getInstance().getPlayerManager().getPlayer(playerUuid, playerName); // Well, this isn't supposed to happen... if (!playerOptional.isPresent()) { @@ -379,10 +393,13 @@ public void processResults( CommandSender sender, Player player, Output.get().sendInfo(sender, message); Output.get().logInfo( "%s initiated rank change: %s", sender.getName(), message ); - String messageGlobal = String.format( "Congratulations! %s ranked up to rank '%s'.", - (player == null ? "Someone" : player.getName()), - (results.getTargetRank() == null ? "" : results.getTargetRank().name) ); - broadcastToWholeServer( sender, messageGlobal ); + if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { + + String messageGlobal = String.format( "Congratulations! %s ranked up to rank '%s'.", + (player == null ? "Someone" : player.getName()), + (results.getTargetRank() == null ? "" : results.getTargetRank().name) ); + broadcastToWholeServer( sender, messageGlobal ); + } } else { String message = String.format( "Unfortunately, %s has been demoted to rank '%s'. %s", (player == null ? "You have" : player.getName()), @@ -391,10 +408,13 @@ public void processResults( CommandSender sender, Player player, Output.get().sendInfo(sender, message); Output.get().logInfo( "%s initiated rank change: %s", sender.getName(), message ); - String messageGlobal = String.format( "Unfortunately, %s has been demoted to rank '%s'.", - (player == null ? "Someone" : player.getName()), - (results.getTargetRank() == null ? "" : results.getTargetRank().name) ); - broadcastToWholeServer( sender, messageGlobal ); + if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { + + String messageGlobal = String.format( "Unfortunately, %s has been demoted to rank '%s'.", + (player == null ? "Someone" : player.getName()), + (results.getTargetRank() == null ? "" : results.getTargetRank().name) ); + broadcastToWholeServer( sender, messageGlobal ); + } } break; case RANKUP_CANT_AFFORD: @@ -413,9 +433,25 @@ public void processResults( CommandSender sender, Player player, break; case RANKUP_FAILURE: Output.get().sendError(sender, - "Failed to retrieve or write data. Your files may be corrupted. " + - "Alert a server administrator."); + "Generic rankup failure. Review rankup details to identify why."); break; + case RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER: + Output.get().sendError(sender, + "Failed to load player."); + break; + case RANKUP_FAILURE_COULD_NOT_LOAD_LADDER: + Output.get().sendError(sender, + "Failed to load ladder."); + break; + case RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK: + Output.get().sendError(sender, + "Failed to assign a rank. Review rankup details to identify why."); + break; + case RANKUP_FAILURE_COULD_NOT_SAVE_PLAYER_FILE: + Output.get().sendError(sender, + "Failed to retrieve or write data. Your files may be corrupted. " + + "Alert a server administrator."); + break; case RANKUP_NO_RANKS: Output.get().sendError(sender, "There are no ranks in this ladder."); break; @@ -431,6 +467,15 @@ public void processResults( CommandSender sender, Player player, "loaded economies.", results.getTargetRank().currency); break; + case RANKUP_LADDER_REMOVED: + Output.get().sendError(sender, "The ladder %s was removed.", ladder); + break; + + case RANKUP_FAILURE_REMOVING_LADDER: + Output.get().sendError(sender, "The ladder %s could not be removed.", ladder); + + break; + case IN_PROGRESS: Output.get().sendError(sender, "Rankup failed to complete normally. No status was set."); break; diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 5e91c344f..4b6452b85 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -145,20 +145,26 @@ public boolean createRank(CommandSender sender, @Command(identifier = "ranks autoConfigure", description = "Auto configures Ranks and Mines using " + "single letters A through Z for both the rank and mine names. If both ranks and mines are " + "generated, they will also be linked together automatically. To set the starting price use " + - "price=x. To set multiplier mult=x. " + + "price=x. To set multiplier mult=x. Cannot autoConfigure if any ranks or mines are defined, " + + "but 'force' will attempt it but at your risk. " + "Default values [full price=50000 mult=1.5]", onlyPlayers = false, permissions = "ranks.set") public void autoConfigureRanks(CommandSender sender, @Wildcard(join=true) @Arg(name = "options", - description = "Options: [full ranks mines price=x mult=x]", + description = "Options: [full ranks mines price=x mult=x force]", def = "full") String options ) { + boolean force = options != null && options.contains( "force" ); + if ( force ) { + options = options.replace( "force", "" ); + } + int rankCount = PrisonRanks.getInstance().getRankManager().getRanks().size(); int mineCount = Prison.get().getPlatform().getModuleElementCount( ModuleElementType.MINE ); - if ( rankCount > 0 || mineCount > 0 ) { + if (!force && ( rankCount > 0 || mineCount > 0 ) ) { String message = String.format( "&3Cannot run &7/ranks autoConfigure &3 with any " + "ranks or mines already setup. Rank count = &7%d&3. Mine count = &7%d", rankCount, mineCount ); @@ -166,6 +172,11 @@ public void autoConfigureRanks(CommandSender sender, return; } + if ( force ) { + String message = String.format( "&aWarning! &3Running autoConfigure with &7force&3 enabled. " + + "Not responsible if mines or ranks collide. "); + Output.get().logWarn( message ); + } String optionHelp = "&b[&7full ranks mines price=&dx &7mult=&dx&b]"; boolean ranks = false; @@ -321,6 +332,11 @@ else if ( plugins.containsKey("PowerfulPerms") ){ } } } + else { + String message = String.format( "&aWarning! &3Rank &7%s &3already exists and is being skipped " + + "along with generating the mine if enabled, along with all of the other features. ", cRank ); + Output.get().logWarn( message ); + } if (price == 0){ price += startingPrice; @@ -336,6 +352,10 @@ else if ( plugins.containsKey("PowerfulPerms") ){ Prison.get().getPlatform().autoCreateMineBlockAssignment(); } + if ( countMines > 0 ) { + Prison.get().getPlatform().autoCreateMineLinerAssignment(); + } + if ( countRanks == 0 ) { Output.get().logInfo( "Ranks autoConfigure: No ranks were created."); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java index 397df4490..2ec884b26 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java @@ -115,7 +115,16 @@ public Rank(Document document) { getRankUpCommands().clear(); Object cmds = document.get("commands"); if ( cmds != null ) { - this.rankUpCommands = (List) cmds; + + List commands = (List) cmds; + for ( String cmd : commands ) { + if ( cmd != null ) { + getRankUpCommands().add( cmd ); + } + } + + // This was allowing nulls to be added to the live commands... +// this.rankUpCommands = (List) cmds; } getMines().clear(); @@ -146,7 +155,15 @@ public Document toDocument() { ret.put("tag", this.tag); ret.put("cost", this.cost); ret.put("currency", this.currency); - ret.put("commands", this.rankUpCommands); + + List cmds = new ArrayList<>(); + for ( String cmd : getRankUpCommands() ) { + // Filters out possible nulls: + if ( cmd != null ) { + cmds.add( cmd ); + } + } + ret.put("commands", cmds); List mineStrings = new ArrayList<>(); if ( getMines() != null ) { diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java index 6036ccfbd..5bc742d61 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java @@ -26,16 +26,24 @@ import com.google.gson.internal.LinkedTreeMap; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.internal.inventory.Inventory; +import tech.mcprison.prison.internal.scoreboard.Scoreboard; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.RankUtil; import tech.mcprison.prison.store.Document; +import tech.mcprison.prison.util.Gamemode; +import tech.mcprison.prison.util.Location; /** * Represents a player with ranks. * * @author Faizaan A. Datoo */ -public class RankPlayer { +public class RankPlayer + implements Player { /* * Fields & Constants @@ -56,6 +64,21 @@ public class RankPlayer { public RankPlayer() { super(); + + this.ranks = new HashMap<>(); + this.prestige = new HashMap<>(); + } + + public RankPlayer( UUID uid ) { + this(); + + this.uid = uid; + } + + public RankPlayer( UUID uid, String playerName ) { + this( uid ); + + checkName( playerName ); } @SuppressWarnings( "unchecked" ) @@ -125,24 +148,67 @@ public Document toDocument() { * Methods */ + public UUID getUUID() { + return uid; + } + + /** + * If the player has any names in the getNames() collection, of which they may not, + * then getDisaplyName() will return the last one set, otherwise it will return + * a null. + */ + public String getDisplayName() { + return getLastName(); + } + + public void setDisplayName(String newDisplayName) { + checkName( newDisplayName ); + } + public boolean isOnline() { + return false; + } + /** + *

Check to see what the last instance of the player's name was, if it + * is a new name, then go ahead and add it to the player's name list. + * If a check was ran from the CONSOLE then it could feed in the name + * CONSOLE so exclude that. + *

+ * + * @param playerName + * @return + */ public boolean checkName( String playerName ) { boolean added = false; - // Check if the last name in the list is not the same as the name passed: - if ( getNames().size() == 0 || - !getNames().get( getNames().size() - 1 ).getName().equalsIgnoreCase( playerName ) ) { + // If the playerName is not valid, don't try to add it: + if ( playerName != null && playerName.trim().length() > 0 && + !"CONSOLE".equalsIgnoreCase( playerName ) ) { - RankPlayerName rpn = new RankPlayerName( playerName, System.currentTimeMillis() ); - getNames().add( rpn ); + String name = getLastName(); - added = true; + // Check if the last name in the list is not the same as the name passed: + if ( name != null && !name.equalsIgnoreCase( playerName ) ) { + + RankPlayerName rpn = new RankPlayerName( playerName, System.currentTimeMillis() ); + getNames().add( rpn ); + + added = true; + } } return added; } + private String getLastName() { + String name = getNames().size() == 0 ? + null : + getNames().get( getNames().size() - 1 ).getName(); + + return name; + } + public List getNames() { if ( names == null ) { @@ -218,14 +284,17 @@ public void removeRank(Rank rank) { /** * Removes a ladder from this player, including whichever rank this player had in it. + * Cannot remove the default ladder. * * @param ladderName The ladder's name. */ - public void removeLadder(String ladderName) { - if (ladderName.equalsIgnoreCase("default")) { - return; + public boolean removeLadder(String ladderName) { + boolean results = false; + if ( !ladderName.equalsIgnoreCase("default") ) { + Integer id = ranks.remove(ladderName); + results = (id != null); } - ranks.remove(ladderName); + return results; } /* @@ -238,6 +307,7 @@ public void removeLadder(String ladderName) { * @param ladder The ladder to check. * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. */ + @Deprecated public Optional getRank(RankLadder ladder) { if (!ranks.containsKey(ladder.name)) { return Optional.empty(); @@ -307,4 +377,124 @@ public Map getRanks() { return uid.hashCode(); } + @Override + public String getName() + { + String name = getLastName(); + + if ( name == null ) { + name = Long.toString( uid.getLeastSignificantBits() ); + } + return name; + } + + @Override + public void dispatchCommand( String command ) + { + // TODO Auto-generated method stub + + } + @Override + public boolean hasPermission( String perm ) { + Output.get().logError( "SpigotOfflinePlayer.hasPermission: Cannot access permissions for offline players." ); + return false; + } + + @Override + public void sendMessage( String message ) { + Output.get().logError( "SpigotOfflinePlayer.sendMessage: Cannot send messages to offline players." ); + } + + @Override + public void sendMessage( String[] messages ) { + Output.get().logError( "SpigotOfflinePlayer.sendMessage: Cannot send messages to offline players." ); + } + + @Override + public void sendRaw( String json ) { + Output.get().logError( "SpigotOfflinePlayer.sendRaw: Cannot send messages to offline players." ); + } + + @Override + public boolean doesSupportColors() { + return false; + } + + @Override + public void give( ItemStack itemStack ) { + Output.get().logError( "SpigotOfflinePlayer.give: Cannot give to offline players." ); + } + + @Override + public Location getLocation() { + Output.get().logError( "SpigotOfflinePlayer.getLocation: Offline players have no location." ); + return null; + } + + @Override + public void teleport( Location location ) { + Output.get().logError( "SpigotOfflinePlayer.teleport: Offline players cannot be teleported." ); + } + + @Override + public void setScoreboard( Scoreboard scoreboard ) { + Output.get().logError( "SpigotOfflinePlayer.setScoreboard: Offline players cannot use scoreboards." ); + } + + @Override + public Gamemode getGamemode() { + Output.get().logError( "SpigotOfflinePlayer.getGamemode: Offline is not a valid gamemode." ); + return null; + } + + @Override + public void setGamemode( Gamemode gamemode ) { + } + + @Override + public Optional getLocale() { + Output.get().logError( "SpigotOfflinePlayer.getLocale: Offline is not a valid gamemode." ); + return null; + } + + @Override + public boolean isOp() { + return false; + } + + @Override + public void updateInventory() { + } + + @Override + public Inventory getInventory() { + return null; + } + + @Override + public void printDebugInventoryInformationToConsole() { + + } + + @Override + public List getPermissions() { + List results = new ArrayList<>(); + + return results; + } + + @Override + public List getPermissions( String prefix ) { + List results = new ArrayList<>(); + + for ( String perm : getPermissions() ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; + } + + } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java index 3cb9b64f0..dc6b5db2f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.ranks.events; +import tech.mcprison.prison.ranks.RankUtil.PromoteForceCharge; +import tech.mcprison.prison.ranks.RankUtil.RankupCommands; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; @@ -18,16 +20,29 @@ public class RankUpEvent { private Rank oldRank; private Rank newRank; private double cost; + + private RankupCommands commad; + private PromoteForceCharge forceCharge; + private boolean canceled = false; + private String cancelReason = null; + /* * Constructor */ - public RankUpEvent(RankPlayer player, Rank oldRank, Rank newRank, double cost) { + public RankUpEvent(RankPlayer player, + Rank oldRank, Rank newRank, double cost, + RankupCommands rankupCommand, + PromoteForceCharge forceCharge ) { + this.player = player; this.oldRank = oldRank; this.newRank = newRank; this.cost = cost; + + this.commad = rankupCommand; + this.forceCharge = forceCharge; } /* @@ -37,7 +52,6 @@ public RankUpEvent(RankPlayer player, Rank oldRank, Rank newRank, double cost) { public RankPlayer getPlayer() { return player; } - public void setPlayer(RankPlayer player) { this.player = player; } @@ -45,7 +59,6 @@ public void setPlayer(RankPlayer player) { public Rank getOldRank() { return oldRank; } - public void setOldRank(Rank oldRank) { this.oldRank = oldRank; } @@ -53,17 +66,64 @@ public void setOldRank(Rank oldRank) { public Rank getNewRank() { return newRank; } - public void setNewRank(Rank newRank) { this.newRank = newRank; } + /** + *

Warning: do not rely upon this field, since it may not + * be accurate since it does not include a custom currency + * if it is being used. Instead, see the new rank for the cost + * which will contain a custom currency. + * @return + */ public double getCost() { return cost; } - public void setCost(double cost) { - this.cost = cost; - } + public RankupCommands getCommad() { + return commad; + } + + + /** + *

This value is only used when using promote, + * demote, or set rank. + *

+ * + *

Possible values are: no_charge, charge_player, + * refund_player + *

+ * @return + */ + public PromoteForceCharge getForceCharge() { + return forceCharge; + } + + + /** + *

Indicates if a rankup was canceled outside of + * prison. There are numerous checks that can cancel the + * the rankup before it even fires this event. + *

+ * + *

This is fired before any currency checks occur. + *

+ * @return + */ + public boolean isCanceled() { + return canceled; + } + public void setCanceled( boolean canceled ) { + this.canceled = canceled; + } + + public String getCancelReason() { + return cancelReason; + } + public void setCancelReason( String cancelReason ) { + this.cancelReason = cancelReason; + } + } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/NewRankPlayerSyncTask.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/NewRankPlayerSyncTask.java new file mode 100644 index 000000000..3c42d4c25 --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/NewRankPlayerSyncTask.java @@ -0,0 +1,28 @@ +package tech.mcprison.prison.ranks.managers; + +import java.util.UUID; + +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.tasks.PrisonRunnable; + +public class NewRankPlayerSyncTask + implements PrisonRunnable { + + private UUID uid; + private String playerName; + + public NewRankPlayerSyncTask( UUID uid, String playerName ) { + super(); + + this.uid = uid; + this.playerName = playerName; + } + + @Override + public void run() { + + PrisonRanks.getInstance().getPlayerManager().addPlayerSyncTask( uid, playerName ); + + } + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index 0603aa263..edc2d53d1 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -20,24 +20,26 @@ import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.TreeMap; import java.util.UUID; import com.google.common.eventbus.Subscribe; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.commands.BaseCommands; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; import tech.mcprison.prison.integration.EconomyIntegration; -import tech.mcprison.prison.integration.IntegrationManager; -import tech.mcprison.prison.integration.IntegrationManager.PlaceHolderFlags; -import tech.mcprison.prison.integration.IntegrationManager.PrisonPlaceHolders; -import tech.mcprison.prison.integration.IntegrationType; import tech.mcprison.prison.integration.ManagerPlaceholders; import tech.mcprison.prison.integration.PlaceHolderKey; +import tech.mcprison.prison.integration.PlaceholderManager; +import tech.mcprison.prison.integration.PlaceholderManager.PlaceHolderFlags; +import tech.mcprison.prison.integration.PlaceholderManager.PrisonPlaceHolders; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.events.player.PlayerJoinEvent; import tech.mcprison.prison.output.Output; @@ -50,6 +52,7 @@ import tech.mcprison.prison.ranks.events.FirstJoinEvent; import tech.mcprison.prison.store.Collection; import tech.mcprison.prison.store.Document; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; import tech.mcprison.prison.util.PlaceholdersUtil; /** @@ -58,18 +61,26 @@ * @author Faizaan A. Datoo */ public class PlayerManager + extends BaseCommands implements ManagerPlaceholders { private Collection collection; private List players; + private TreeMap playersByName; private List translatedPlaceHolderKeys; + private transient Set playerErrors; public PlayerManager(Collection collection) { + super("PlayerMangager"); + this.collection = collection; this.players = new ArrayList<>(); + this.playersByName = new TreeMap<>(); + + this.playerErrors = new HashSet<>(); Prison.get().getEventBus().register(this); } @@ -86,7 +97,18 @@ public PlayerManager(Collection collection) { */ public void loadPlayer(String playerFile) throws IOException { Document document = collection.get(playerFile).orElseThrow(IOException::new); - players.add(new RankPlayer(document)); + RankPlayer rankPlayer = new RankPlayer(document); + + players.add( rankPlayer ); + + // add by uuid: + playersByName.put( rankPlayer.getUUID().toString(), rankPlayer ); + + // add by name: + if ( rankPlayer.getNames().size() > 0 ) { + playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); + + } } /** @@ -134,6 +156,12 @@ public void savePlayers() throws IOException { { String message = "An error occurred while saving the player files: " + player.filename(); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + Output.get().logError(message, e); } } @@ -147,7 +175,15 @@ public List getPlayers() { return players; } - /** + public TreeMap getPlayersByName() { + return playersByName; + } + + public Set getPlayerErrors() { + return playerErrors; + } + + /** *

Get the player, if they don't exist, add them. *

* @@ -155,22 +191,51 @@ public List getPlayers() { * @return */ public Optional getPlayer(UUID uid, String playerName) { - Optional results = players.stream().filter(player -> player.uid.equals(uid)).findFirst(); + + Optional results = Optional.ofNullable( null ); + boolean dirty = false; + + for ( RankPlayer rankPlayer : players ) { + if ( uid != null && rankPlayer.uid.equals(uid) || + uid == null && playerName != null && playerName.trim().length() > 0 && + rankPlayer.getDisplayName() != null && + rankPlayer.getDisplayName().equalsIgnoreCase( playerName ) ) { + + // This checks to see if they have a new name, if so, then adds it to the history: + // But the UID must match: + if ( uid != null && rankPlayer.uid.equals(uid) ) { + dirty = rankPlayer.checkName( playerName ); + } + + results = Optional.ofNullable( rankPlayer ); + break; + } + } + +// Optional results = players.stream().filter( +// player -> (uid != null ? +// player.uid.equals(uid) : +// ( playerName != null || playerName.trim().length() == 0 ? false : +// player.checkName( playerName )))).findFirst(); if ( !results.isPresent() ) { results = Optional.ofNullable( addPlayer(uid, playerName) ); + dirty = results.isPresent(); } - // check to see if the name has changed, if so, then save because the new name was added: - if ( playerName != null && playerName.trim().length() > 0 && - results.get().checkName( playerName ) ) { + // Save if dirty (change or new): + if ( dirty && results.isPresent() ) { try { savePlayer( results.get() ); } catch ( IOException e ) { - Output.get().logWarn( - String.format( "PlayerManager.getPlayer(): Failed to add new player name: %s. %s", - playerName, e.getMessage()) ); + String message = String.format( "PlayerManager.getPlayer(): Failed to add new player name: %s. %s", + playerName, e.getMessage()); + if ( !getPlayerErrors().contains( message ) ) { + + getPlayerErrors().add( message ); + Output.get().logError( message ); + } } } @@ -180,37 +245,78 @@ public Optional getPlayer(UUID uid, String playerName) { private RankPlayer addPlayer( UUID uid, String playerName ) { - // We need to create a new player data file. - RankPlayer newPlayer = new RankPlayer(); - newPlayer.uid = uid; - newPlayer.ranks = new HashMap<>(); - newPlayer.prestige = new HashMap<>(); - - players.add(newPlayer); - - try { - savePlayer(newPlayer); - - // Assign the player to the default rank: - String ladder = null; // will set to the "default" ladder - String rank = null; // will set to the "default" rank - - // Set the rank to the default ladder and the default rank. The results are logged - // before the results are returned, so can ignore the results: - @SuppressWarnings( "unused" ) - RankupResults results = new RankUtil().setRank(newPlayer, ladder, rank, - playerName, "FirstJoinEvent"); - - - Prison.get().getEventBus().post(new FirstJoinEvent(newPlayer)); - } - catch (IOException e) { - Output.get().logError( - "Failed to create new player data file for player " + - (playerName == null ? "" : playerName) + - " target filename: " + newPlayer.filename(), e); + RankPlayer results = null; + + // addPlayer can only be rank in the primary thread: + if ( PrisonTaskSubmitter.isPrimaryThread() ) { + results = addPlayerSyncTask( uid, playerName ); + } + else if ( !getPlayersByName().containsKey( playerName )) { + + // Submit the sync task to add player. But since this is an + // async thread, we can only return a null. Future requests + // for this player's placeholder will resolve successfully + // and a return value of null is perfectly acceptable. + NewRankPlayerSyncTask syncTask = new NewRankPlayerSyncTask( uid, playerName ); + PrisonTaskSubmitter.runTaskLater( syncTask, 0 ); + } + return results; + } + + protected RankPlayer addPlayerSyncTask( UUID uid, String playerName ) { + RankPlayer newPlayer = null; + + // Treat this like how we setup a singleton with sychronization with a + // check before and after to see if the object has been inserted: + + if ( uid != null && playerName != null && + playerName.trim().length() > 0 && !"CONSOLE".equalsIgnoreCase( playerName ) && + !getPlayersByName().containsKey( playerName )) { + + synchronized( getPlayersByName() ) { + + // recheck to ensure that the player's name is not in the getPlayersByName() + // collection... it could have been added since submitting the sync task: + + if ( !getPlayersByName().containsKey( playerName ) ) { + + // We need to create a new player data file. + newPlayer = new RankPlayer( uid, playerName ); + newPlayer.checkName( playerName ); + + players.add(newPlayer); + getPlayersByName().put( playerName, newPlayer ); + + try { + savePlayer(newPlayer); + + Player player = getPlayer( null, playerName, uid ); + + // Assign the player to the default rank: + String ladder = null; // will set to the "default" ladder + String rank = null; // will set to the "default" rank + + // Set the rank to the default ladder and the default rank. The results are logged + // before the results are returned, so can ignore the results: + @SuppressWarnings( "unused" ) + RankupResults results = new RankUtil().setRank(player, newPlayer, ladder, rank, + playerName, "FirstJoinEvent"); + + + Prison.get().getEventBus().post(new FirstJoinEvent(newPlayer)); + } + catch (IOException e) { + Output.get().logError( + "Failed to create new player data file for player " + + (playerName == null ? "" : playerName) + + " target filename: " + newPlayer.filename(), e); + } + } + + } } + return newPlayer; } @@ -222,9 +328,10 @@ private RankPlayer addPlayer( UUID uid, String playerName ) { Player player = event.getPlayer(); - if (!getPlayer(player.getUUID(), player.getName()).isPresent()) { - addPlayer( player.getUUID(), player.getName() ); - } + // Player is auto added if they do not exist when calling getPlayer so don't try to + // add them a second time. + getPlayer(player.getUUID(), player.getName()); + } @@ -248,7 +355,49 @@ public String getPlayerRankName( RankPlayer rankPlayer, String ladderName ) { return sb.toString(); } - public String getPlayerRankTag( RankPlayer rankPlayer, String ladderName ) { + + public String getPlayerRankNumber( RankPlayer rankPlayer, String ladderName ) { + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getRanks().isEmpty()) { + for (Map.Entry entry : rankPlayer.getRanks().entrySet()) { + if ( ladderName == null || + ladderName != null && entry.getKey().name.equalsIgnoreCase( ladderName )) { + + if ( sb.length() > 0 ) { + sb.append(" "); + } + + int rankNumber = rankNumber(entry.getValue()); + sb.append( Integer.toString( rankNumber ) ); + } + } + } + + return sb.toString(); + } + + /** + *

This counts how many ranks there are from the bottom to the + * current rank level. The lowest rank has a value of 1, no rank + * will be zero. + *

+ * @param value + * @return + */ + private int rankNumber( Rank value ) { + int results = 0; + if ( value != null ) { + Rank r = value; + while ( r != null ) { + results++; + r = r.getRankPrior(); + } + } + return results; + } + + public String getPlayerRankTag( RankPlayer rankPlayer, String ladderName ) { StringBuilder sb = new StringBuilder(); if ( !rankPlayer.getRanks().isEmpty()) { @@ -301,7 +450,7 @@ public String getPlayerNextRankCost( RankPlayer rankPlayer, String ladderName, b StringBuilder sb = new StringBuilder(); if ( !rankPlayer.getRanks().isEmpty()) { - DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat dFmt = new DecimalFormat("#,##0"); for (Map.Entry entry : rankPlayer.getRanks().entrySet()) { RankLadder key = entry.getKey(); if ( ladderName == null || @@ -332,13 +481,18 @@ public String getPlayerNextRankCostPercent( RankPlayer rankPlayer, String ladder Player prisonPlayer = PrisonAPI.getPlayer(rankPlayer.uid).orElse(null); if( prisonPlayer == null ) { - Output.get().logError( String.format( "getPlayerNextRankCostPercent: " + - "Could not load player: %s", rankPlayer.uid) ); + String message = String.format( "getPlayerNextRankCostPercent: " + + "Could not load player: %s", rankPlayer.uid); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } return "0"; } if ( !rankPlayer.getRanks().isEmpty()) { - DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat dFmt = new DecimalFormat("#,##0"); for (Map.Entry entry : rankPlayer.getRanks().entrySet()) { RankLadder key = entry.getKey(); if ( ladderName == null || @@ -371,8 +525,14 @@ public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName Player prisonPlayer = PrisonAPI.getPlayer(rankPlayer.uid).orElse(null); if( prisonPlayer == null ) { - Output.get().logError( String.format( "getPlayerNextRankCostBar: " + - "Could not load player: %s", rankPlayer.uid) ); + String message = String.format( "getPlayerNextRankCostBar: " + + "Could not load player: %s", rankPlayer.uid); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + return "0"; } @@ -394,7 +554,7 @@ public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName double balance = getPlayerBalance(prisonPlayer,rank); - sb.append( Prison.get().getIntegrationManager(). + sb.append( Prison.get().getPlaceholderManager(). getProgressBar( balance, cost, false )); } @@ -405,18 +565,36 @@ public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName return sb.toString(); } + /** + *

This function will use the player's current balance in the currency that the next ranks + * uses, and will subtract the cost of the next rank from their current balance. This + * function returns what would remain after the transaction. If this return a negative value + * then it's an indicator that the player cannot yet afford the next rank. + *

+ * + * @param rankPlayer + * @param ladderName + * @param formatted + * @return + */ public String getPlayerNextRankCostRemaining( RankPlayer rankPlayer, String ladderName, boolean formatted ) { StringBuilder sb = new StringBuilder(); Player prisonPlayer = PrisonAPI.getPlayer(rankPlayer.uid).orElse(null); if( prisonPlayer == null ) { - Output.get().logError( String.format( "getPlayerNextRankCostRemaining: " + - "Could not load player: %s", rankPlayer.uid) ); + String message = String.format( "getPlayerNextRankCostRemaining: " + + "Could not load player: %s", rankPlayer.uid); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + return "0"; } if ( !rankPlayer.getRanks().isEmpty()) { - DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat dFmt = new DecimalFormat("#,##0"); for (Map.Entry entry : rankPlayer.getRanks().entrySet()) { RankLadder key = entry.getKey(); if ( ladderName == null || @@ -433,9 +611,9 @@ public String getPlayerNextRankCostRemaining( RankPlayer rankPlayer, String ladd double remaining = cost - balance; - if ( remaining < 0 ) { - remaining = 0; - } +// if ( remaining < 0 ) { +// remaining = 0; +// } if ( formatted ) { sb.append( PlaceholdersUtil.formattedSize( remaining )); @@ -451,18 +629,36 @@ public String getPlayerNextRankCostRemaining( RankPlayer rankPlayer, String ladd return sb.toString(); } + /** + *

This gets the player's balance as a formatted String based upon the ranks' + * custom currency, if it's set. If there is a problem getting the custom + * currency, then it will return a value of zero for the player's balance, which + * will prevent the player from ranking up due to insufficient funds. + *

+ * + * @param rankPlayer + * @param ladderName + * @param formatted + * @return + */ private String getPlayerBalance( RankPlayer rankPlayer, String ladderName, boolean formatted ) { StringBuilder sb = new StringBuilder(); Player prisonPlayer = PrisonAPI.getPlayer(rankPlayer.uid).orElse(null); if( prisonPlayer == null ) { - Output.get().logError( String.format( "getPlayerBalance: " + - "Could not load player: %s", rankPlayer.uid) ); + String message = String.format( "getPlayerBalance: " + + "Could not load player: %s", rankPlayer.uid); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + return "0"; } if ( !rankPlayer.getRanks().isEmpty()) { - DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat dFmt = new DecimalFormat("#,##0"); for (Map.Entry entry : rankPlayer.getRanks().entrySet()) { RankLadder key = entry.getKey(); if ( ladderName == null || @@ -490,19 +686,35 @@ private String getPlayerBalance( RankPlayer rankPlayer, String ladderName, boole return sb.toString(); } + /** + *

This gets the player's balance, and if the rank is provided, it will check to + * see if there is a custom currency that needs to be used for that rank. If there + * is a custom currency, then it will check the balance for that player using that + * currency. + *

+ * + * @param player + * @param rank + * @return + */ private double getPlayerBalance(Player player, Rank rank) { double playerBalance = 0; - if ( rank.currency != null ) { + if ( rank != null && rank.currency != null ) { EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() .getEconomyForCurrency( rank.currency ); if ( currencyEcon != null ) { playerBalance = currencyEcon.getBalance( player, rank.currency ); } else { - Output.get().logError( - String.format( "Failed to load Economy to get the balance for " + - "player %s with a currency of %s.", - player.getName(), rank.currency )); + String message = String.format( "Failed to load Economy to get the balance for " + + "player %s with a currency of %s.", + player.getName(), rank.currency ); + + if ( !getPlayerErrors().contains( message ) ) { + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + } } else { @@ -512,9 +724,15 @@ private double getPlayerBalance(Player player, Rank rank) { if ( economy != null ) { playerBalance = economy.getBalance( player ); } else { - Output.get().logError( - String.format( "Failed to load Economy to get the balance for player %s.", - player.getName() )); + String message = String.format( "Failed to load Economy to get the balance for player %s.", + player.getName() ); + Output.get().logError( message ); + if ( !getPlayerErrors().contains( message ) ) { + + getPlayerErrors().add( message ); + Output.get().logError( message ); + } + } } @@ -565,6 +783,14 @@ public String getPlayerNextRankTag( RankPlayer rankPlayer, String ladderName ) { return sb.toString(); } + /** + *

Entry point for translating placeholders. + *

+ * @param playerUuid + * @param playerName + * @param identifier + * @return + */ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, String identifier ) { String results = null; @@ -572,8 +798,8 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, List placeHolderKeys = getTranslatedPlaceHolderKeys(); - if ( !identifier.startsWith( IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { - identifier = IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; + if ( !identifier.startsWith( PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED )) { + identifier = PlaceholderManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED + identifier; } for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { @@ -609,6 +835,13 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, results = getPlayerRankName( rankPlayer, ladderName ); break; + case prison_rn: + case prison_rank_number: + case prison_rn_laddername: + case prison_rank_number_laddername: + results = getPlayerRankNumber( rankPlayer, ladderName ); + break; + case prison_rt: case prison_rank_tag: case prison_rt_laddername: @@ -720,13 +953,13 @@ public List getTranslatedPlaceHolderKeys() { for ( RankLadder ladder : ladders ) { for ( PrisonPlaceHolders ph : placeHolders ) { String key = ph.name().replace( - IntegrationManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.name ). + PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.name ). toLowerCase(); PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, ladder.name ); if ( ph.getAlias() != null ) { String aliasName = ph.getAlias().name().replace( - IntegrationManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.name ). + PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.name ). toLowerCase(); placeholder.setAliasName( aliasName ); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java index 2cca4dfe3..eef6ba57c 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java @@ -260,45 +260,51 @@ public Optional getRankEscaped(String name) { */ public boolean removeRank(Rank rank) { // ... remove it from each user, bumping them down to the next lowest rank... - for (RankLadder ladder : PrisonRanks.getInstance().getLadderManager() - .getLaddersWithRank(rank.id)) { - int next = - Math.max(0, ladder.getPositionOfRank(rank) - 1); // either one less, or the bottom - - Optional newRank = ladder.getByPosition(next); - if (!newRank.isPresent()) { - // TODO Do something here ... default rank! - return false; - } + + final Rank newRank = ( rank.getRankPrior() != null ? + rank.getRankPrior() : + rank.getRankNext() ); + if ( newRank == null ) { + Output.get().logError("Remove Rank Warning: No fallback rank exists so players with " + + "the rank that is being removed will have no rank on that ladder."); + } + + final boolean[] success = {true}; + for (RankLadder ladder : PrisonRanks.getInstance().getLadderManager() + .getLaddersWithRank(rank.id)) { + // Move each player in this ladder to the new rank PrisonRanks.getInstance().getPlayerManager().getPlayers().forEach(rankPlayer -> { - if (rankPlayer.getRank(ladder).isPresent()) { - rankPlayer.removeRank(rankPlayer.getRank(ladder).get()); - rankPlayer.addRank(ladder, newRank.get()); + Rank curRank = rankPlayer.getRank(ladder.name); + if ( curRank != null && rank.equals( curRank ) ) { + rankPlayer.removeRank(curRank); + if ( newRank != null ) { + rankPlayer.addRank(ladder, newRank); + } + try { PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); } catch (IOException e) { - Output.get().logError("Couldn't save player file.", e); + Output.get().logError("RemoveRank: Couldn't save player file.", e); } - PrisonAPI.debug("Player %s is now %s", rankPlayer.uid.getLeastSignificantBits(), - newRank.get().name); + PrisonAPI.debug("Player %s is now %s", rankPlayer.getName(), + newRank.name); } }); + + + // ... remove it from each ladder it was in... + ladder.removeRank(ladder.getPositionOfRank(rank)); + try { + PrisonRanks.getInstance().getLadderManager().saveLadder(ladder); + } catch (IOException e) { + success[0] = false; + Output.get().logError("RemoveRank: Could not save ladder " + ladder.name + ".", e); + } + } - // ... remove it from each ladder it was in... - final boolean[] success = {true}; - PrisonRanks.getInstance().getLadderManager().getLaddersWithRank(rank.id) - .forEach(rankLadder -> { - rankLadder.removeRank(rankLadder.getPositionOfRank(rank)); - try { - PrisonRanks.getInstance().getLadderManager().saveLadder(rankLadder); - } catch (IOException e) { - success[0] = false; - Output.get().logError("Could not save ladder.", e); - } - }); if(!success[0]) { return false; } diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 4b908bd7c..60010b669 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -50,7 +50,8 @@ dependencies { implementation 'me.lucko.luckperms:luckperms-api:4.0' - implementation 'com.github.cryptomorin:XSeries:7.5.4' + implementation 'com.github.cryptomorin:XSeries:7.6.0.0.1' +// implementation 'com.github.cryptomorin:XSeries:7.5.4' // implementation 'com.github.cryptomorin:XSeries:7.2.1' // implementation 'com.github.cryptomorin:XSeries:6.3.2.1' @@ -102,7 +103,7 @@ shadowJar { include(dependency('org.bstats:bstats-bukkit:1.5')) include(dependency('me.clip:placeholderapi:2.9.1')) include(dependency('org.inventivetalent.spiget-update:bukkit:1.4.2-SNAPSHOT')) - include(dependency('com.github.cryptomorin:XSeries:7.5.4')) + include(dependency('com.github.cryptomorin:XSeries:7.6.0.0.1')) include(project(':prison-core')) include(project(':prison-mines')) include(project(':prison-ranks')) diff --git a/prison-spigot/lib/CustomItems_v3.7.17_api.jar b/prison-spigot/lib/CustomItems_v3.7.17_api.jar new file mode 100644 index 000000000..7ee7c654a Binary files /dev/null and b/prison-spigot/lib/CustomItems_v3.7.17_api.jar differ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 5e036d942..e70c1527d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Random; import java.util.UUID; import java.util.stream.Collectors; @@ -56,11 +57,13 @@ import tech.mcprison.prison.internal.Scheduler; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.internal.platform.Capability; import tech.mcprison.prison.internal.platform.Platform; import tech.mcprison.prison.internal.scoreboard.ScoreboardManager; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.modules.Module; import tech.mcprison.prison.modules.ModuleElement; @@ -71,6 +74,8 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.Rank; +import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.spigot.game.SpigotCommandSender; import tech.mcprison.prison.spigot.game.SpigotOfflinePlayer; @@ -82,6 +87,7 @@ import tech.mcprison.prison.spigot.util.SpigotYamlFileIO; import tech.mcprison.prison.store.Storage; import tech.mcprison.prison.util.BlockType; +import tech.mcprison.prison.util.Bounds.Edges; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; @@ -102,6 +108,8 @@ class SpigotPlatform private Storage storage; private SpigotPlaceholders placeholders; + + /** * This is only for junit testing. @@ -250,7 +258,7 @@ public Optional getOfflinePlayer(UUID uuid) { return getOfflinePlayer(null, uuid); } private Optional getOfflinePlayer(String name, UUID uuid) { - SpigotOfflinePlayer player = null; + Player player = null; if ( uuid != null ) { OfflinePlayer oPlayer = Bukkit.getOfflinePlayer( uuid ); @@ -279,6 +287,23 @@ else if ( oPlayer == null || oPlayer.getName() == null ) { } } + // If player is not available, then try to get a RankPlayer instance of the player: + if ( player == null ) { + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + + RankPlayer rankPlayer = pm.getPlayer( uuid, name ).orElse( null ); + if ( rankPlayer != null ) { + if ( uuid != null && rankPlayer.getUUID().equals( uuid ) || + uuid == null && name != null && rankPlayer.getName() != null && + rankPlayer.getName().equalsIgnoreCase( name )) { + + player = rankPlayer; + } + } + } + } + return Optional.ofNullable( player ); @@ -489,6 +514,20 @@ public void logCore( String message ) sender.sendMessage(message); } } + + /** + * This does not translate any color codes. + */ + @Override + public void logPlain( String message ) + { + ConsoleCommandSender sender = Bukkit.getConsoleSender(); + if (sender == null) { + Bukkit.getLogger().info(message); + } else { + sender.sendMessage(message); + } + } @Override public void debug(String message, Object... format) { if (!plugin.debug) { @@ -743,22 +782,59 @@ public boolean getConfigBooleanTrue( String key ) { return ( val == null || val.trim().equalsIgnoreCase( "true" ) ); } - /** - * This listing that is returned, should be the XMaterial enum name - * for the blocks that are valid on the server. - * - * @return - */ @Override - public void getAllPlatformBlockTypes( List blockTypes ) { + public int getConfigInt( String key, int defaultValue ) { + int results = defaultValue; + + String config = getConfigString(key); - SpigotUtil.getAllPlatformBlockTypes( blockTypes ); + if ( config != null && config.trim().length() > 0) { + + try { + results = Integer.parseInt( config ); + } + catch ( NumberFormatException e ) { + Output.get().logInfo( "Invalid config.yml value. The setting " + + "%s should be an integer but had a value of [%s]", + key, config ); + } + + } + + return results; } + + + /** + * Setup hooks in to the valid prison block types. This will be only the + * block types that have tested to be valid on the server that is running + * prison. This provides full compatibility to the admins that if a block + * is listed, then it's usable. No more guessing or finding out after the + * fact that a block that was used was invalid for their version of minecraft. + */ + public PrisonBlockTypes getPrisonBlockTypes() { + return SpigotPrison.getInstance().getPrisonBlockTypes(); + } +// /** +// * This listing that is returned, should be the XMaterial enum name +// * for the blocks that are valid on the server. +// * +// * @return +// */ +// @Override +// public void getAllPlatformBlockTypes( List blockTypes ) { +// +// SpigotUtil.getAllPlatformBlockTypes( blockTypes ); +// +// SpigotUtil.getAllCustomBlockTypes( blockTypes ); +// } + @Override public PrisonBlock getPrisonBlock( String blockName ) { - return SpigotUtil.getPrisonBlock( blockName ); + return getPrisonBlockTypes().getBlockTypesByName( blockName ); +// return SpigotUtil.getPrisonBlock( blockName ); } @@ -1077,6 +1153,31 @@ public void autoCreateMineBlockAssignment() { } } + @Override + public void autoCreateMineLinerAssignment() { + + MineManager mm = PrisonMines.getInstance().getMineManager(); + List mines = mm.getMines(); + + for ( Mine mine : mines ) { + + if ( mine.getLinerData().toSaveString().trim().isEmpty() ) { + mine.getLinerData().setLiner( Edges.walls, getRandomLinerType(), true ); + mine.getLinerData().setLiner( Edges.bottom, getRandomLinerType(), true ); + + mm.saveMine( mine ); + } + } + } + + private LinerPatterns getRandomLinerType() { + LinerPatterns[] liners = LinerPatterns.values(); + + // Exclude the last LinerPattern since it is "repair". + int pos = new Random().nextInt( liners.length - 1 ); + return liners[pos]; + } + /** * This function grabs a rolling sub set of blocks from the startPos and working backwards * up to the specified length. The result set will be less than the specified length if at diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java index 67170a3e6..f127795a5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java @@ -40,6 +40,7 @@ import tech.mcprison.prison.PrisonCommand; import tech.mcprison.prison.alerts.Alerts; import tech.mcprison.prison.integration.Integration; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.managers.MineManager; @@ -58,6 +59,7 @@ import tech.mcprison.prison.spigot.commands.PrisonSpigotMinesCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotPrestigeCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotRanksCommands; +import tech.mcprison.prison.spigot.commands.sellall.SellAllPrisonCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.Spigot113; import tech.mcprison.prison.spigot.compat.Spigot18; @@ -65,6 +67,7 @@ import tech.mcprison.prison.spigot.configs.GuiConfig; import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.configs.SellAllConfig; +import tech.mcprison.prison.spigot.customblock.CustomItems; import tech.mcprison.prison.spigot.economies.EssentialsEconomy; import tech.mcprison.prison.spigot.economies.GemsEconomy; import tech.mcprison.prison.spigot.economies.SaneEconomy; @@ -76,7 +79,6 @@ import tech.mcprison.prison.spigot.placeholder.MVdWPlaceholderIntegration; import tech.mcprison.prison.spigot.placeholder.PlaceHolderAPIIntegration; import tech.mcprison.prison.spigot.player.SlimeBlockFunEventListener; -import tech.mcprison.prison.spigot.sellall.SellAllCommands; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; /** @@ -103,6 +105,9 @@ public class SpigotPrison extends JavaPlugin { private GuiConfig guiConfig; private SellAllConfig sellAllConfig; + private PrisonBlockTypes prisonBlockTypes; + + private static SpigotPrison config; public static SpigotPrison getInstance(){ @@ -160,8 +165,8 @@ public void onEnable() { Prison.get().init(new SpigotPlatform(this), Bukkit.getVersion()); Prison.get().getLocaleManager().setDefaultLocale(getConfig().getString("default-language", "en_US")); - + // Manually register Listeners with Bukkit: Bukkit.getPluginManager().registerEvents(new ListenersPrisonManager(),this); Bukkit.getPluginManager().registerEvents(new AutoManager(), this); Bukkit.getPluginManager().registerEvents(new OnBlockBreakEventListener(), this); @@ -169,23 +174,28 @@ public void onEnable() { Bukkit.getPluginManager().registerEvents(new SpigotListener(), this); - initIntegrations(); - // NOTE: Put all commands within the initModulesAndCommands() function. initModulesAndCommands(); applyDeferredIntegrationInitializations(); + + + // After all the integrations have been loaded and the deferred tasks ran, + // then run the deferred Module setups: + initDeferredModules(); + + initMetrics(); - Prison.get().getPlatform().getPlaceholders().printPlaceholderStats(); + + // These stats are displayed within the initDeferredModules(): + //Prison.get().getPlatform().getPlaceholders().printPlaceholderStats(); + PrisonCommand cmdVersion = Prison.get().getPrisonCommands(); - - - // if (doAlertAboutConvert) { // Alerts.getInstance().sendAlert( // "&7An old installation of Prison has been detected. &3Type /prison convert to convert your old data automatically. &7If you already converted, delete the 'Prison.old' folder so that we stop nagging you."); @@ -224,18 +234,17 @@ public void onDisable() { } public FileConfiguration getGuiConfig() { - if ( guiConfig == null ) { + if (guiConfig == null) { guiConfig = new GuiConfig(); } return guiConfig.getFileGuiConfig(); } public FileConfiguration getSellAllConfig() { - if (sellAllConfig == null && SellAllCommands.isEnabled() ) { - - sellAllConfig = new SellAllConfig(); - } - return sellAllConfig == null ? null : sellAllConfig.getFileSellAllConfig(); + // Let this like this or it wont update when you do /Sellall etc and will need a server restart. + sellAllConfig = new SellAllConfig(); + sellAllConfig.initialize(); + return sellAllConfig.getFileSellAllConfig(); } public FileConfiguration getMessagesConfig() { @@ -253,8 +262,21 @@ public AutoManagerFeatures getAutoFeatures() { public void setAutoFeatures( AutoManagerFeatures autoFeatures ) { this.autoFeatures = autoFeatures; } - + + public static String format(String format){ + + // This might be enabled in the future + // Check if version's higher than 1.16 + //if (new BluesSpigetSemVerComparator().compareMCVersionTo("1.16.0") > 0){ + // Matcher matcher = hexPattern.matcher(format); + // while (matcher.find()) { + // String color = format.substring(matcher.start(), matcher.end()); + // format = format.replace(color, ChatColor.valueOf(color) + ""); + // matcher = hexPattern.matcher(format); + // } + //} + return format == null ? "" : ChatColor.translateAlternateColorCodes('&', format); } @@ -382,6 +404,8 @@ private void initIntegrations() { registerIntegration(new MVdWPlaceholderIntegration()); registerIntegration(new PlaceHolderAPIIntegration()); + registerIntegration(new CustomItems()); + // registerIntegration(new WorldGuard6Integration()); // registerIntegration(new WorldGuard7Integration()); } @@ -407,9 +431,12 @@ public void reloadIntegrationsPlaceholders() { private void registerIntegration(Integration integration) { - integration.setRegistered(Bukkit.getPluginManager().isPluginEnabled(integration.getProviderName())); - integration.integrate(); - PrisonAPI.getIntegrationManager().register(integration); + boolean isRegistered = Bukkit.getPluginManager().isPluginEnabled(integration.getProviderName()); + String version = ( isRegistered ? Bukkit.getPluginManager() + .getPlugin( integration.getProviderName() ) + .getDescription().getVersion() : null ); + + PrisonAPI.getIntegrationManager().register(integration, isRegistered, version ); } /** @@ -442,7 +469,7 @@ private void initModulesAndCommands() { Prison.get().getCommandHandler().registerCommands( new PrisonSpigotRanksCommands() ); // NOTE: If ranks module is enabled, then try to register prestiges commands if enabled: - if ( !isPrisonConfig( "prestiges") ) { + if ( isPrisonConfig( "prestiges") || isPrisonConfig( "prestige.enabled" ) ) { // Enable the setup of the prestige related commands only if prestiges is enabled: Prison.get().getCommandHandler().registerCommands( new PrisonSpigotPrestigeCommands() ); } @@ -454,18 +481,20 @@ private void initModulesAndCommands() { Prison.get().getModuleManager().getDisabledModules().add( PrisonRanks.MODULE_NAME ); } - // Try to load the mines and ranks that have the ModuleElement placeholders: - // Both the mine and ranks modules must be enabled. - if (modulesConf.getBoolean("mines") && modulesConf.getBoolean("ranks")) { - linkMinesAndRanks(); - } - // Only register the command if it is enabled so it will not conflict with other sellall plugins if they are used: - if ( SellAllCommands.isEnabled() ) { - - // Do not hit this function here. It will lazy initialize if needed: - //getSellAllConfig(); - getCommand("sellall").setExecutor(new SellAllCommands()); + // The following linkMinesAndRanks() function must be called only after the + // Module deferred tasks are ran. +// // Try to load the mines and ranks that have the ModuleElement placeholders: +// // Both the mine and ranks modules must be enabled. +// if (modulesConf.getBoolean("mines") && modulesConf.getBoolean("ranks")) { +// linkMinesAndRanks(); +// } + + // Load sellAll if enabled + if (SellAllPrisonCommands.isEnabled()){ + + Prison.get().getCommandHandler().registerCommands(new SellAllPrisonCommands()); + } // This registers the admin's /gui commands @@ -473,10 +502,39 @@ private void initModulesAndCommands() { } + + /** + * This will initialize any process that has been setup in the modules that + * needs to be ran after all of the integrations have been fully loaded and initialized. + * + */ + private void initDeferredModules() { + + for ( Module module : Prison.get().getModuleManager().getModules() ) { + + module.deferredStartup(); + } + + + // Reload placeholders: + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + + // Finally link mines and ranks if both are loaded: + linkMinesAndRanks(); + } + + + /** + * Try to link the mines and ranks that have the ModuleElement placeholders: + * Both the mine and ranks modules must be enabled to try to link them all + * together. + */ private void linkMinesAndRanks() { - if (PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() && PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled()) { + if (PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() && + PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled()) { RankManager rm = PrisonRanks.getInstance().getRankManager(); MineManager mm = PrisonMines.getInstance().getMineManager(); @@ -547,4 +605,36 @@ public boolean isPrisonConfig( String configId ) { boolean results = config != null && config.equalsIgnoreCase( "true" ); return results; } + + /** + * Setup hooks in to the valid prison block types. This will be only the + * block types that have tested to be valid on the server that is running + * prison. This provides full compatibility to the admins that if a block + * is listed, then it's usable. No more guessing or finding out after the + * fact that a block that was used was invalid for their version of minecraft. + */ + public PrisonBlockTypes getPrisonBlockTypes() { + + if ( prisonBlockTypes == null ) { + synchronized ( PrisonBlockTypes.class ) { + if ( prisonBlockTypes == null ) { + + // Setup hooks in to the valid prison block types, which must be done + // after all the integrations have been initialized. This will be only + // the block types that have tested to be valid on the server that is + // running prison. This provides full compatibility to the admins that + // if a block is listed, then it's usable. No more guessing or finding + // out after the fact that a block that was used was invalid for + // their version of minecraft. + PrisonBlockTypes pbt = new PrisonBlockTypes(); + pbt.addBlockTypes( SpigotUtil.getAllPlatformBlockTypes() ); + pbt.addBlockTypes( SpigotUtil.getAllCustomBlockTypes() ); + this.prisonBlockTypes = pbt; + + } + } + } + + return prisonBlockTypes; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotScheduler.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotScheduler.java index 6180d7d15..5b07194a5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotScheduler.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotScheduler.java @@ -34,28 +34,39 @@ public SpigotScheduler(SpigotPrison plugin) { this.scheduler = plugin.getServer().getScheduler(); } - @Override public int runTaskLater(Runnable run, long delay) { + @Override + public int runTaskLater(Runnable run, long delay) { return scheduler.runTaskLater(plugin, run, delay).getTaskId(); } - @Override public int runTaskLaterAsync(Runnable run, long delay) { + @Override + public int runTaskLaterAsync(Runnable run, long delay) { return scheduler.runTaskLaterAsynchronously(plugin, run, delay).getTaskId(); } - @Override public int runTaskTimer(Runnable run, long delay, long interval) { + @Override + public int runTaskTimer(Runnable run, long delay, long interval) { return scheduler.runTaskTimer(plugin, run, delay, interval).getTaskId(); } - @Override public int runTaskTimerAsync(Runnable run, long delay, long interval) { + @Override + public int runTaskTimerAsync(Runnable run, long delay, long interval) { return scheduler.runTaskTimerAsynchronously(plugin, run, delay, interval).getTaskId(); } - @Override public void cancelTask(int taskId) { + @Override + public void cancelTask(int taskId) { scheduler.cancelTask(taskId); } - @Override public void cancelAll() { + @Override + public void cancelAll() { scheduler.cancelTasks(plugin); } + + @Override + public boolean isPrimaryThread() { + return this.plugin.getServer().isPrimaryThread(); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java index a0f593e53..d00a21fed 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java @@ -19,24 +19,32 @@ package tech.mcprison.prison.spigot; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.integration.CustomBlockIntegration; +import tech.mcprison.prison.integration.Integration; +import tech.mcprison.prison.integration.IntegrationType; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.inventory.InventoryType; import tech.mcprison.prison.internal.inventory.Viewable; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.BlockTestStats; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.BlockType; @@ -159,6 +167,59 @@ public static ItemStack getItemStack( XMaterial xMaterial, int amount ) { return bukkitStack; } + public static SpigotItemStack getSpigotItemStack( XMaterial xMaterial, int amount ) { + SpigotItemStack itemStack = new SpigotItemStack( getItemStack( xMaterial, amount ) ); + + return itemStack; + } + + /** + * Used in AutoManagerFeatures. + * + * @param player + * @param itemStack + * @return + */ + public static HashMap addItemToPlayerInventory( + Player player, SpigotItemStack itemStack ) { + HashMap results = new HashMap<>(); + + HashMap overflow = player.getInventory().addItem( itemStack.getBukkitStack() ); + Set keys = overflow.keySet(); + for ( Integer key : keys ) { + results.put( key, new SpigotItemStack( overflow.get( key ) )); + } + + return results; + } + + /** + * Used in AutoManagerFeatures. + * @param player + * @param itemStack + */ + public static void dropPlayerItems( Player player, SpigotItemStack itemStack ) { + + org.bukkit.Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); + + player.getWorld().dropItem( dropPoint, itemStack.getBukkitStack() ); + + } + + public static boolean playerInventoryContainsAtLeast( Player player, + SpigotItemStack itemStack, int quantity ) { + boolean results = player.getInventory().containsAtLeast( + itemStack.getBukkitStack(), quantity ); + + return results; + } + + public static HashMap playerInventoryRemoveItem( Player player, SpigotItemStack itemStack ) { + HashMap results = player.getInventory().removeItem( itemStack.getBukkitStack() ); + + return results; + } + /** * Note that XMaterial.parseMaterial() may work well for v1.13.x and higher, * but it does not represent the correct block types in lower versions, @@ -167,7 +228,8 @@ public static ItemStack getItemStack( XMaterial xMaterial, int amount ) { * * @param blockTypes */ - public static void getAllPlatformBlockTypes( List blockTypes ) { + public static List getAllPlatformBlockTypes() { + List blockTypes = new ArrayList<>(); for ( XMaterial xMat : XMaterial.values() ) { if ( xMat.isSupported() ) { @@ -206,8 +268,38 @@ public static void getAllPlatformBlockTypes( List blockTypes ) { } } } + + return blockTypes; + } + + public static List getAllCustomBlockTypes() { + List blockTypes = new ArrayList<>(); + + List customBlockInterfaces = + Prison.get().getIntegrationManager().getAllForType( IntegrationType.CUSTOMBLOCK ); + + for ( Integration integration : customBlockInterfaces ) + { + if ( integration.hasIntegrated() && integration instanceof CustomBlockIntegration ) { + CustomBlockIntegration blkInt = (CustomBlockIntegration) integration; + + List blocks = blkInt.getCustomBlockList(); + + if ( blocks.size() > 0 ) { + blockTypes.addAll( blocks ); + } + + Output.get().logInfo( "&3Custom Block Integration: &7%s &3registered &7%d &3blocks " + + "&with the PrisonBlockType of &7%s&3.", + blkInt.getDisplayName(), blocks.size(), + blkInt.getBlockType().name() ); + } + } + + return blockTypes; } + /** *

This will take a string name of a block, and convert it to the * String name of a XMaterial. If it cannot directly perform the @@ -474,36 +566,10 @@ public static org.bukkit.Location prisonLocationToBukkit(Location prisonLocation * ItemStack */ - public static tech.mcprison.prison.internal.ItemStack bukkitItemStackToPrison( - ItemStack bukkitStack) { + public static SpigotItemStack bukkitItemStackToPrison( ItemStack bukkitStack) { - if (bukkitStack == null || bukkitStack.getType().equals(Material.AIR)) { - return new tech.mcprison.prison.internal.ItemStack(0, BlockType.AIR); - } - - ItemMeta meta; - if (!bukkitStack.hasItemMeta()) { - meta = Bukkit.getItemFactory().getItemMeta(bukkitStack.getType()); - } else { - meta = bukkitStack.getItemMeta(); - } - - String displayName = null; - - if (meta.hasDisplayName()) { - displayName = meta.getDisplayName(); - } - - int amount = bukkitStack.getAmount(); - - BlockType type = SpigotPrison.getInstance().getCompatibility() - .getBlockType( bukkitStack ); -// BlockType type = materialToBlockType(bukkitStack.getType()); - - List lore = meta.hasLore() ? meta.getLore() : Collections.emptyList(); - String[] lore_arr = lore.toArray(new String[lore.size()]); - - return new tech.mcprison.prison.internal.ItemStack(displayName, amount, type, lore_arr); + SpigotItemStack results = new SpigotItemStack( bukkitStack ); + return results; } public static ItemStack prisonItemStackToBukkit( @@ -540,13 +606,21 @@ public static ItemStack prisonItemStackToBukkit( return bukkitStack; } - + + public static List getDrops(SpigotBlock block, SpigotItemStack tool) { + List ret = new ArrayList<>(); + + block.getWrapper().getDrops( tool.getBukkitStack() ) + .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); + + return ret; +} + /* * InventoryType */ - public static InventoryType bukkitInventoryTypeToPrison( - org.bukkit.event.inventory.InventoryType type) { + public static InventoryType bukkitInventoryTypeToPrison( org.bukkit.event.inventory.InventoryType type) { return InventoryType.valueOf(type.name()); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManager.java index 951734a51..12a91705c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManager.java @@ -6,13 +6,14 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.PlayerArmorStandManipulateEvent; -import org.bukkit.inventory.ItemStack; import com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; /** @@ -84,20 +85,30 @@ public AutoManager() { @Override @EventHandler(priority=EventPriority.LOW) public void onBlockBreak(BlockBreakEvent e) { - super.onBlockBreak(e); + + if ( isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + +// Output.get().logInfo( "#### AutoManager.OnBlockBreak: " + +// " x: " + e.getBlock().getX() + " y: " + e.getBlock().getY() + +// " z: " + e.getBlock().getZ() + " cancelled: " + e.isCancelled()); + + genericBlockEvent( e ); + } } @Override @EventHandler(priority=EventPriority.LOW) public void onTEBlockExplode(TEBlockExplodeEvent e) { - super.onTEBlockExplode(e); + if ( isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + genericBlockExplodeEvent( e ); + } } @Override - public void doAction( Mine mine, BlockBreakEvent e ) { - applyAutoEvents( e, mine ); + public void doAction( SpigotBlock block, Mine mine, BlockBreakEvent e ) { + applyAutoEvents( block, e, mine ); } @@ -114,49 +125,66 @@ public void manipulate(PlayerArmorStandManipulateEvent e) { } } - private void applyAutoEvents( BlockBreakEvent e, Mine mine ) { - - if ( isBoolean( AutoFeatures.isAutoManagerEnabled ) && !e.isCancelled() ) { + //TODO Use the SpigotBlock within these functions so it can use the new block model and the custom blocks if they exist + private void applyAutoEvents( SpigotBlock block, BlockBreakEvent e, Mine mine) { + + if (isBoolean(AutoFeatures.isAutoManagerEnabled) && !e.isCancelled()) { Player player = e.getPlayer(); + SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + + + double lorePickup = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Pickup, player ); double loreSmelt = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Smelt, player ); double loreBlock = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Block, player ); - boolean permPickup = player.hasPermission( - getMessage( AutoFeatures.permissionAutoPickup ) ) || + boolean permPickup = lorePickup == 100.0 || lorePickup > 0 && lorePickup <= getRandom().nextDouble() * 100; - boolean permSmelt = player.hasPermission( - getMessage( AutoFeatures.permissionAutoSmelt ) ) || + boolean permSmelt = loreSmelt == 100.0 || loreSmelt > 0 && loreSmelt <= getRandom().nextDouble() * 100; - boolean permBlock = player.hasPermission( - getMessage( AutoFeatures.permissionAutoBlock ) ) || + boolean permBlock = loreBlock == 100.0 || loreBlock > 0 && loreBlock <= getRandom().nextDouble() * 100; - - // - + + // NOTE: Using isPermissionSet so players that are op'd to not auto enable everything. + // Ops will have to have the perms set to actually use them. + // AutoPickup - if ( permPickup || isBoolean( AutoFeatures.autoPickupEnabled )) { + if ( (mine != null || mine == null && !isBoolean( AutoFeatures.autoPickupLimitToMines )) && + (permPickup || isBoolean( AutoFeatures.autoPickupEnabled ) || + player.isPermissionSet( getMessage( AutoFeatures.permissionAutoPickup ) )) ) { - autoFeaturePickup(e, player ); + int count = autoFeaturePickup( block, player, itemInHand ); + autoPickupCleanup( player, itemInHand, count, e ); } - // AutoSmelt - if ( permSmelt || isBoolean( AutoFeatures.autoSmeltEnabled )){ + if ( (mine != null || mine == null && !isBoolean( AutoFeatures.autoSmeltLimitToMines )) && + (permSmelt || isBoolean( AutoFeatures.autoSmeltEnabled ) || + player.isPermissionSet( getMessage( AutoFeatures.permissionAutoSmelt ) )) ){ - autoFeatureSmelt( e, player ); + autoFeatureSmelt( block, player, itemInHand ); } // AutoBlock - if ( permBlock || isBoolean( AutoFeatures.autoBlockEnabled )) { + if ( (mine != null || mine == null && !isBoolean( AutoFeatures.autoBlockLimitToMines )) && + (permBlock || isBoolean( AutoFeatures.autoBlockEnabled ) || + player.isPermissionSet(getMessage( AutoFeatures.permissionAutoBlock ) ) ) ) { - autoFeatureBlock( e, player ); +// Output.get().logInfo( "AutoManager.applyAutoEnvents: AutoBlock enabled = %b " + +// "%s hasPerm = %b isSet = %b has lore = %b ", +// isBoolean( AutoFeatures.autoBlockEnabled ), +// getMessage( AutoFeatures.permissionAutoBlock ), +// player.hasPermission(getMessage( AutoFeatures.permissionAutoBlock ) ), +// player.isPermissionSet(getMessage( AutoFeatures.permissionAutoBlock ) ), +// loreBlock +// ); + autoFeatureBlock( block, player, itemInHand ); } // NOTE: This may be in duplication... durability is calculated in auto pickup: @@ -180,17 +208,14 @@ private void applyAutoEvents( BlockBreakEvent e, Mine mine ) { // A block was broke... so record that event on the tool: - if ( isBoolean( AutoFeatures.loreTrackBlockBreakCount ) && - e.isCancelled()) { + if ( isBoolean( AutoFeatures.loreTrackBlockBreakCount ) && e.isCancelled()) { + // The event was canceled, so the block was successfully broke, so increment the name counter: - ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( player ); - - itemLoreCounter( itemInHand, - getMessage( AutoFeatures.loreBlockBreakCountName ), 1 ); +// ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( player ); + itemLoreCounter( itemInHand, getMessage( AutoFeatures.loreBlockBreakCountName ), 1 ); } } - } @@ -219,37 +244,31 @@ private void applyAutoEvents( BlockBreakEvent e, Mine mine ) { */ private void applyAutoEvents( TEBlockExplodeEvent e, Mine mine, int blockCount ) { - Player p = e.getPlayer(); + Player player = e.getPlayer(); // double lorePickup = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Pickup, p ); // double loreSmelt = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Smelt, p ); // double loreBlock = doesItemHaveAutoFeatureLore( ItemLoreEnablers.Block, p ); // -// boolean permPickup = p.hasPermission( "prison.autofeatures.pickup" ) || +// boolean permPickup = p.isPermissionSet( "prison.autofeatures.pickup" ) || // lorePickup == 100.0 || // lorePickup > 0 && lorePickup <= getRandom().nextDouble() * 100; -// boolean permSmelt = p.hasPermission( "prison.autofeatures.smelt" ) || +// boolean permSmelt = p.isPermissionSet( "prison.autofeatures.smelt" ) || // loreSmelt == 100.0 || // loreSmelt > 0 && loreSmelt <= getRandom().nextDouble() * 100; -// boolean permBlock = p.hasPermission( "prison.autofeatures.block" ) || +// boolean permBlock = p.isPermissionSet( "prison.autofeatures.block" ) || // loreBlock == 100.0 || // loreBlock > 0 && loreBlock <= getRandom().nextDouble() * 100; // if ( permPickup || permSmelt || permBlock || -// isAreEnabledFeatures()) - { - - - ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( p ); - - - if ( e.isCancelled() ) { - // The event was canceled, so the block was successfully broke, so increment the name counter: - - itemLoreCounter( itemInHand, - getMessage( AutoFeatures.loreBlockExplosionCountName ), blockCount ); - } - } - } +// isAreEnabledFeatures()) + + + SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + if (e.isCancelled()) { + // The event was canceled, so the block was successfully broke, so increment the name counter: + itemLoreCounter(itemInHand, getMessage(AutoFeatures.loreBlockExplosionCountName), blockCount); + } + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index e7950c53e..59dda1504 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -1,10 +1,6 @@ package tech.mcprison.prison.spigot.autofeatures; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Random; +import java.util.*; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -12,6 +8,7 @@ import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.block.Block; +import org.bukkit.configuration.Configuration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; @@ -33,36 +30,39 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; /** *

This class controls the data and the basic functions for auto features. * It loads the settings only once, and uses them on each event that is raised * in order to reduce overhead in reloading all of them on each block break - * event. Then, if an external process should happen to save changes to + * event. Then, if an external process should happen to save changes to * these settings, then it will reload the settings so they are always * current. *

- * + * * */ public class AutoManagerFeatures - extends OnBlockBreakEventListener { - + extends OnBlockBreakEventListener { + public enum ItemLoreCounters { - + // NOTE: the String value must include a trailing space! - + itemLoreBlockBreakCount( ChatColor.LIGHT_PURPLE + "Prison Blocks Mined:" + - ChatColor.GRAY + " "), - + ChatColor.GRAY + " "), + itemLoreBlockExplodeCount( ChatColor.LIGHT_PURPLE + "Prison Blocks Exploded:" + - ChatColor.GRAY + " "); - - + ChatColor.GRAY + " "); + + private final String lore; ItemLoreCounters( String lore ) { this.lore = lore; @@ -70,9 +70,9 @@ public enum ItemLoreCounters { public String getLore() { return lore; } - + } - + public enum ItemLoreEnablers { Pickup, Smelt, @@ -81,136 +81,42 @@ public enum ItemLoreEnablers { } private Random random = new Random(); - - private AutoFeaturesFileConfig autoFeaturesConfig = null; - -// private Configuration autoConfigs; - -// private boolean isAutoManagerEnabled = false; - -// private boolean dropItemsIfInventoryIsFull = false; -// private boolean playSoundIfInventoryIsFull = false; -// private boolean hologramIfInventoryIsFull = false; - -// private boolean autoPickupEnabled = false; -// private boolean autoPickupAllBlocks = false; -// private boolean autoPickupCobbleStone = false; -// private boolean autoPickupStone = false; -// private boolean autoPickupGoldOre = false; -// private boolean autoPickupIronOre = false; -// private boolean autoPickupCoalOre = false; -// private boolean autoPickupDiamondOre = false; -// private boolean autoPickupRedstoneOre = false; -// private boolean autoPickupEmeraldOre = false; -// private boolean autoPickupQuartzOre = false; -// private boolean autoPickupLapisOre = false; -// private boolean autoPickupSnowBall = false; -// private boolean autoPickupGlowstoneDust = false; - - // AutoSmelt booleans from configs -// private boolean autoSmeltEnabled = false; -// private boolean autoSmeltAllBlocks = false; -// private boolean autoSmeltGoldOre = false; -// private boolean autoSmeltIronOre = false; - - // AutoBlock booleans from configs -// private boolean autoBlockEnabled = false; -// private boolean autoBlockAllBlocks = false; -// private boolean autoBlockGoldBlock = false; -// private boolean autoBlockIronBlock = false; -// private boolean autoBlockCoalBlock = false; -// private boolean autoBlockDiamondBlock = false; -// private boolean autoBlockRedstoneBlock = false; -// private boolean autoBlockEmeraldBlock = false; -// private boolean autoBlockQuartzBlock = false; -// private boolean autoBlockPrismarineBlock = false; -// private boolean autoBlockLapisBlock = false; -// private boolean autoBlockSnowBlock = false; -// private boolean autoBlockGlowstone = false; - - + + private AutoFeaturesFileConfig autoFeaturesConfig = null; + + public AutoManagerFeatures() { super(); - + setup(); } - + private void setup() { - + this.autoFeaturesConfig = new AutoFeaturesFileConfig(); - -// this.autoConfigs = getAutoFeaturesConfig(); -// this.autoConfigs = SpigotPrison.getInstance().getAutoFeaturesConfig(); - -// this.isAutoManagerEnabled = isBoolean( AutoFeatures.isAutoManagerEnabled ); - - //if (isAreEnabledFeatures()) - { - -// this.dropItemsIfInventoryIsFull = isBoolean( AutoFeatures.dropItemsIfInventoryIsFull ); -// this.playSoundIfInventoryIsFull = isBoolean( AutoFeatures.playSoundIfInventoryIsFull ); -// this.hologramIfInventoryIsFull = isBoolean( AutoFeatures.hologramIfInventoryIsFull ); - - // AutoPickup booleans from configs -// this.autoPickupEnabled = isBoolean( AutoFeatures.autoPickupEnabled ); -// this.autoPickupAllBlocks = isBoolean( AutoFeatures.autoPickupAllBlocks ); -// this.autoPickupCobbleStone = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupCobbleStone ); -// this.autoPickupStone = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupStone ); -// this.autoPickupGoldOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupGoldOre ); -// this.autoPickupIronOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupIronOre ); -// this.autoPickupCoalOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupCoalOre ); -// this.autoPickupDiamondOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupDiamondOre ); -// this.autoPickupRedstoneOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupRedStoneOre ); -// this.autoPickupEmeraldOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupEmeraldOre ); -// this.autoPickupQuartzOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupQuartzOre ); -// this.autoPickupLapisOre = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupLapisOre ); -// this.autoPickupSnowBall = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupSnowBall ); -// this.autoPickupGlowstoneDust = autoPickupAllBlocks || isBoolean( AutoFeatures.autoPickupGlowstoneDust ); - - // AutoSmelt booleans from configs -// this.autoSmeltEnabled = isBoolean( AutoFeatures.autoSmeltEnabled ); -// this.autoSmeltAllBlocks = isBoolean( AutoFeatures.autoSmeltAllBlocks ); -// this.autoSmeltGoldOre = autoSmeltAllBlocks || isBoolean( AutoFeatures.autoSmeltGoldOre ); -// this.autoSmeltIronOre = autoSmeltAllBlocks || isBoolean( AutoFeatures.autoSmeltIronOre ); - - // AutoBlock booleans from configs -// this.autoBlockEnabled = isBoolean( AutoFeatures.autoBlockEnabled ); -// this.autoBlockAllBlocks = isBoolean( AutoFeatures.autoBlockAllBlocks ); -// this.autoBlockGoldBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockGoldBlock ); -// this.autoBlockIronBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockIronBlock ); -// this.autoBlockCoalBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockCoalBlock ); -// this.autoBlockDiamondBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockDiamondBlock ); -// this.autoBlockRedstoneBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockRedstoneBlock ); -// this.autoBlockEmeraldBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockEmeraldBlock ); -// this.autoBlockQuartzBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockQuartzBlock ); -// this.autoBlockPrismarineBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockPrismarineBlock ); -// this.autoBlockLapisBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockLapisBlock ); -// this.autoBlockSnowBlock = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockSnowBlock ); -// this.autoBlockGlowstone = autoBlockAllBlocks || isBoolean( AutoFeatures.autoBlockGlowstone ); - - } + } - + public AutoFeaturesFileConfig getAutoFeaturesConfig() { return autoFeaturesConfig; } - + protected boolean isBoolean( AutoFeatures feature ) { return autoFeaturesConfig.isFeatureBoolean( feature ); } - + protected String getMessage( AutoFeatures feature ) { return autoFeaturesConfig.getFeatureMessage( feature ); } - + // /** // *

This lazy loading of the FileConfiguration for the AutoFeatures will ensure // * the file is loaded from the file system only one time and only when it is first // * used. This ensures that if it is never used, it is never loaded in to memory. // *

-// * +// * // * @return // */ // private FileConfiguration getAutoFeaturesConfig() { @@ -221,207 +127,225 @@ protected String getMessage( AutoFeatures feature ) { // } // return autoFeaturesConfig; // } - - + + // /** -// *

This change in this function, to move it in to this class, allows the +// *

This change in this function, to move it in to this class, allows the // * reloading of the parameters that controls all of the behaviors whenever // * the data is saved. // *

-// * +// * // * @return // */ // public boolean saveAutoFeaturesConfig() { // boolean success = false; // FileConfiguration afConfig = getAutoFeaturesConfig(); -// +// // if ( afConfig != null ) { // AutoFeaturesFileConfig afc = new AutoFeaturesFileConfig(); // success = afc.saveConf(afConfig); -// +// // // reload the internal settings: // setup(); // } // return success; // } - + /** *

If the fortune level is zero, then this function will always return a value of one. *

- * - *

If it is non-zero, then this function will return a value of one, plus an - * equally distributed chance of returning an additional 0 to fortuneLevel + * + *

If it is non-zero, then this function will return a value of one, plus an + * equally distributed chance of returning an additional 0 to fortuneLevel * bonuses of that material. *

- * + * *

This applies to "all" materials within the mine, including chests, shulkers, - * signs etc... + * signs etc... *

- * + * * @param fortuneLevel * @return */ - public int getDropCount(int fortuneLevel) { - int j = - fortuneLevel == 0 ? - 1 : - 1 + getRandom().nextInt(fortuneLevel + 1); + public int getDropCount(int fortuneLevel) { + int j = + fortuneLevel == 0 ? + 1 : + 1 + getRandom().nextInt(fortuneLevel + 1); - return j; - } + return j; + } - protected boolean hasSilkTouch (ItemStack itemInHand){ - return itemInHand.getEnchantments().containsKey(Enchantment.SILK_TOUCH); + protected boolean hasSilkTouch (SpigotItemStack itemInHand){ + return itemInHand.getBukkitStack().getEnchantments().containsKey(Enchantment.SILK_TOUCH); + } + + protected boolean hasFortune(SpigotItemStack itemInHand){ + return itemInHand.getBukkitStack().getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS); + } + protected short getFortune(SpigotItemStack itemInHand){ + return (short) itemInHand.getBukkitStack().getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); } - - protected boolean hasFortune(ItemStack itemInHand){ - return itemInHand.getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS); - } - protected short getFortune(ItemStack itemInHand){ - return (short) itemInHand.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); - } /* - * Drops are wrong with old 1.14.4 releases of spigot - * but got fixed in newer versions. - * - * For older versions, a good way to get the right drops would be to use BlockDropItemEvent.getItems(), but it's deprecated - * */ - protected int autoPickup( boolean autoPickup, Player player, ItemStack itemInHand, BlockBreakEvent e ) { + * Drops are wrong with old 1.14.4 releases of spigot + * but got fixed in newer versions. + * + * For older versions, a good way to get the right drops would be to use BlockDropItemEvent.getItems(), but it's deprecated + * */ + protected int autoPickup( boolean autoPickup, Player player, SpigotItemStack itemInHand, SpigotBlock block ) { + //, BlockBreakEvent e ) { int count = 0; if (autoPickup) { // The following is not the correct drops: - Collection drops = e.getBlock().getDrops(itemInHand); + Collection drops = SpigotUtil.getDrops(block, itemInHand); +// Collection drops = e.getBlock().getDrops(itemInHand); + + if (drops != null && drops.size() > 0 ) { - + // Need better drop calculation that is not using the getDrops function. short fortuneLevel = getFortune(itemInHand); - - + + // Adds in additional drop items: calculateDropAdditions( itemInHand, drops ); - + if ( isBoolean( AutoFeatures.isCalculateSilkEnabled ) && hasSilkTouch( itemInHand )) { - + calculateSilkTouch( itemInHand, drops ); } // Add the item to the inventory - for ( ItemStack itemStack : drops ) { - + for ( SpigotItemStack itemStack : drops ) { + if ( isBoolean( AutoFeatures.isCalculateFortuneEnabled ) ) { // calculateFortune directly modifies the quantity on the blocks ItemStack: calculateFortune( itemStack, fortuneLevel ); } - + count += itemStack.getAmount(); - dropExtra( player.getInventory().addItem(itemStack), player, e.getBlock() ); + dropExtra( SpigotUtil.addItemToPlayerInventory( player, itemStack ), player, block ); +// dropExtra( player.getInventory().addItem(itemStack), player, block ); } - // Auto pickup has been successful. Now clean up. - if ( count > 0 ) { - - // Set the broken block to AIR and cancel the event - e.setCancelled(true); - e.getBlock().setType(Material.AIR); - - // Maybe needed to prevent drop side effects: - e.getBlock().getDrops().clear(); - - // calculate durability impact: Include item durability resistance. - if ( isBoolean( AutoFeatures.isCalculateDurabilityEnabled ) ) { - - // value of 0 = normal durability. Value 100 = never calculate durability. - int durabilityResistance = 0; - if ( isBoolean( AutoFeatures.loreDurabiltyResistance ) ) { - durabilityResistance = getDurabilityResistance( itemInHand, - getMessage( AutoFeatures.loreDurabiltyResistanceName ) ); - } - - calculateDurability( player, itemInHand, durabilityResistance ); - } +// autoPickupCleanup( player, itemInHand, count ); + } + } + return count; + } + + + protected void autoPickupCleanup( Player player, SpigotItemStack itemInHand, int count, BlockBreakEvent e ) + { + // Auto pickup has been successful. Now clean up. + if ( count > 0 ) { + + // Set the broken block to AIR and cancel the event + e.setCancelled(true); + e.getBlock().setType(Material.AIR); + + // Maybe needed to prevent drop side effects: + e.getBlock().getDrops().clear(); + + // calculate durability impact: Include item durability resistance. + if ( isBoolean( AutoFeatures.isCalculateDurabilityEnabled ) ) { + + // value of 0 = normal durability. Value 100 = never calculate durability. + int durabilityResistance = 0; + if ( isBoolean( AutoFeatures.loreDurabiltyResistance ) ) { + durabilityResistance = getDurabilityResistance( itemInHand, + getMessage( AutoFeatures.loreDurabiltyResistanceName ) ); } + + calculateDurability( player, itemInHand, durabilityResistance ); } } - return count; } - protected void autoSmelt( boolean autoSmelt, String sourceStr, String destinationStr, Player p, Block block ) { - + protected void autoSmelt( boolean autoSmelt, String sourceStr, String destinationStr, Player p, SpigotBlock block ) { + if ( autoSmelt ) { XMaterial source = SpigotUtil.getXMaterial( sourceStr ); XMaterial destination = SpigotUtil.getXMaterial( destinationStr ); - - ItemStack sourceStack = source.parseItem(); - ItemStack destStack = destination.parseItem(); - + + SpigotItemStack sourceStack = new SpigotItemStack( source.parseItem() ); + SpigotItemStack destStack = new SpigotItemStack( destination.parseItem() ); + if ( sourceStack != null && destStack != null && - p.getInventory().containsAtLeast( sourceStack, 1 ) ) { - + SpigotUtil.playerInventoryContainsAtLeast( p, sourceStack, 1 ) ) { + int count = itemCount(source, p); if ( count > 0 ) { sourceStack.setAmount( count ); destStack.setAmount( count ); - - p.getInventory().removeItem(sourceStack); - - dropExtra( p.getInventory().addItem(destStack), p, block ); + + SpigotUtil.playerInventoryRemoveItem( p, sourceStack ); + + HashMap extras = SpigotUtil.addItemToPlayerInventory( p, destStack ); + dropExtra( extras, p, block ); } } - + } } - protected void autoBlock( boolean autoBlock, String sourceStr, String destinationStr, Player p, Block block ) { + protected void autoBlock( boolean autoBlock, String sourceStr, String destinationStr, + Player p, SpigotBlock block ) { autoBlock(autoBlock, sourceStr, destinationStr, 9, p, block ); } - - protected void autoBlock( boolean autoBlock, String sourceStr, String destinationStr, int targetCount, Player p, Block block ) { - + + protected void autoBlock( boolean autoBlock, String sourceStr, String destinationStr, + int targetCount, Player p, SpigotBlock block ) { + XMaterial source = SpigotUtil.getXMaterial( sourceStr ); XMaterial destination = SpigotUtil.getXMaterial( destinationStr ); - + if ( autoBlock ) { int count = itemCount(source, p); if ( count >= targetCount ) { int mult = count / targetCount; - + p.getInventory().removeItem(SpigotUtil.getItemStack(source, mult * targetCount)); - dropExtra( p.getInventory().addItem(SpigotUtil.getItemStack(destination, mult)), p, block); + + SpigotItemStack itemStack = SpigotUtil.getSpigotItemStack(destination, mult); + HashMap extras = SpigotUtil.addItemToPlayerInventory( p, itemStack ); +// HashMap extras = p.getInventory().addItem(SpigotUtil.getItemStack(destination, mult)); + dropExtra( extras, p, block); } } } // /** -// *

Lapis is really dyed ink sacks, so need to have special processing to ensure we process the +// *

Lapis is really dyed ink sacks, so need to have special processing to ensure we process the // * correct material, and not just any ink sack. // *

-// * +// * // *

Warning: this will not work with minecraft 1.15.x since magic numbers have been // * eliminated. // *

-// * +// * // * @param autoBlock // * @param player // */ // protected void autoBlockLapis( boolean autoBlock, Player player, Block block ) { // if ( autoBlock ) { -// // ink_sack = 351:4 -// +// // ink_sack = 351:4 +// // Material mat = Material.matchMaterial( "INK_SACK" ); // short typeId = 4; // // // try both methods to get lapis: -// +// // try { // convertLapisBlock( player, block, mat, typeId ); // } // catch ( Exception e ) { // // Ignore exception. // } -// +// // mat = Material.matchMaterial( "lapis_lazuli" ); // if ( mat != null ) { // @@ -440,44 +364,44 @@ protected void autoBlock( boolean autoBlock, String sourceStr, String destinatio // private void convertLapisBlock( Player player, Block block, Material mat, int typeId ) { // XMaterial xMat = SpigotUtil.getXMaterial( mat ); // int count = itemCount(xMat, typeId, player); -// +// // if ( count >= 9 ) { // int mult = count / 9; -// +// // ItemStack removeLapisItemStack = XMaterial.LAPIS_LAZULI.parseItem(); // removeLapisItemStack.setAmount( mult * 9 ); -// +// //// ItemStack removeLapisItemStack = new ItemStack( mat, mult * 9, (short) typeId); // player.getInventory().removeItem(removeLapisItemStack); -// +// // dropExtra( player.getInventory().addItem(new ItemStack(Material.LAPIS_BLOCK, mult)), player, block ); -// +// // } // } // private void convertLapisBlock( Player player, Block block, Material mat ) { // XMaterial xMat = SpigotUtil.getXMaterial( mat ); // int count = itemCount(xMat, player); -// +// // if ( count >= 9 ) { // int mult = count / 9; -// +// // ItemStack removeLapisItemStack = XMaterial.LAPIS_LAZULI.parseItem(); // removeLapisItemStack.setAmount( mult * 9 ); // //// ItemStack removeLapisItemStack = new ItemStack( mat, mult * 9 ); // player.getInventory().removeItem(removeLapisItemStack); -// +// // dropExtra( player.getInventory().addItem( // new ItemStack(Material.LAPIS_BLOCK, mult)), player, block ); // } // } - + private int itemCount(XMaterial source, Player player) { int count = 0; if ( source != null ) { ItemStack testStack = source.parseItem(); - + PlayerInventory inv = player.getInventory(); for (ItemStack is : inv.getContents() ) { if ( is != null && is.isSimilar( testStack ) ) { @@ -487,21 +411,21 @@ private int itemCount(XMaterial source, Player player) { } return count; } - - + + // private int itemCount(Material source, int typeId, Player player) { // int count = 0; // PlayerInventory inv = player.getInventory(); -// +// // for (ItemStack is : inv.getContents()) { -// +// // if ( is != null && is.getType() != null && is.getType().compareTo( source ) == 0 ) { // count += is.getAmount(); // } // } // return count; // } - + /** *

If the player does not have any more inventory room for the current items, then * it will drop the extra. @@ -510,92 +434,118 @@ private int itemCount(XMaterial source, Player player) { * @param player * @param block */ - private void dropExtra( HashMap extra, Player player, Block block ) { + private void dropExtra( HashMap extra, Player player, SpigotBlock block ) { + + Configuration sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); + if ( extra != null && extra.size() > 0 ) { - for ( ItemStack itemStack : extra.values() ) { - + + if (sellAllConfig.getString("Options.Full_Inv_AutoSell").equalsIgnoreCase("true")) { + + if (sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable").equalsIgnoreCase("true")){ + + UUID playerUUID = player.getUniqueId(); + + if (sellAllConfig.getString("Users." + playerUUID + ".isEnabled") != null){ + if (!sellAllConfig.getString("Users." + playerUUID + ".isEnabled").equalsIgnoreCase("true")){ + return; + } + } + } + + if (sellAllConfig.getString("Options.Full_Inv_AutoSell_Notification").equalsIgnoreCase("true")) { + player.sendMessage(SpigotPrison.format(SpigotPrison.getInstance().getMessagesConfig().getString("Message.SellAllAutoSell"))); + } + + Bukkit.dispatchCommand(player, "sellall sell"); + + return; + } + + for ( SpigotItemStack itemStack : extra.values() ) { + if ( isBoolean( AutoFeatures.dropItemsIfInventoryIsFull ) ) { - - Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); - - player.getWorld().dropItem( dropPoint, itemStack ); + +// Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); +// +// player.getWorld().dropItem( dropPoint, itemStack ); + + SpigotUtil.dropPlayerItems( player, itemStack ); notifyPlayerThatInventoryIsFull( player, block ); } else { notifyPlayerThatInventoryIsFullLosingItems( player, block ); } - + } } } - private void notifyPlayerThatInventoryIsFull( Player player, Block block ) { + private void notifyPlayerThatInventoryIsFull( Player player, SpigotBlock block ) { notifyPlayerWithSound( player, block, AutoFeatures.inventoryIsFull ); } - + @SuppressWarnings( "unused" ) - private void notifyPlayerThatInventoryIsFullDroppingItems( Player player, Block block ) { + private void notifyPlayerThatInventoryIsFullDroppingItems( Player player, SpigotBlock block ) { notifyPlayerWithSound( player, block, AutoFeatures.inventoryIsFullDroppingItems ); } - - private void notifyPlayerThatInventoryIsFullLosingItems( Player player, Block block ) { + + private void notifyPlayerThatInventoryIsFullLosingItems( Player player, SpigotBlock block ) { notifyPlayerWithSound( player, block, AutoFeatures.inventoryIsFullLosingItems ); - + } - - private void notifyPlayerWithSound( Player player, Block block, AutoFeatures messageId ) { + + private void notifyPlayerWithSound( Player player, SpigotBlock block, AutoFeatures messageId ) { String message = autoFeaturesConfig.getFeatureMessage( messageId ); - + // Play sound when full - if ( isBoolean( AutoFeatures.playSoundIfInventoryIsFull ) ) { + if (isBoolean(AutoFeatures.playSoundIfInventoryIsFull)) { Prison.get().getMinecraftVersion() ; - + // This hard coding the Sound enum causes failures in spigot 1.8.8 since it does not exist: Sound sound; try { - sound = Sound.valueOf("ANVIL_USE"); // pre 1.9 sound + sound = Sound.valueOf("ANVIL_USE"); // pre 1.9 sound } catch(IllegalArgumentException e) { - sound = Sound.valueOf("BLOCK_ANVIL_PLACE"); // post 1.9 sound + sound = Sound.valueOf("BLOCK_ANVIL_PLACE"); // post 1.9 sound } - + player.playSound(player.getLocation(), sound, 10F, 1F); } - + // holographic display for showing full inventory does not work well. // if ( isBoolean( AutoFeatures.hologramIfInventoryIsFull ) ) { // displayMessageHologram( block, message , player); // } // else { - actionBarVersion(player, message); + actionBarVersion(player, message); // } } private void actionBarVersion(Player player, String message) { - if ( new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0 ) { + if (new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0) { displayActionBarMessage(player, message); - } + } else { - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, - TextComponent.fromLegacyText(SpigotPrison.format(message))); + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(SpigotPrison.format(message))); } } /** - * This is not usable since it not only prevents the player from mining when it is + * This is not usable since it not only prevents the player from mining when it is * displayed, but it cannot be seen since it is shown above the player's head. - * - * The player can continue to mine other materials even though one kind of resource + * + * The player can continue to mine other materials even though one kind of resource * be full. - * + * * @param block * @param message * @param p */ @SuppressWarnings( "unused" ) private void displayMessageHologram(Block block, String message, Player p){ - ArmorStand as = (ArmorStand) block.getLocation().getWorld().spawnEntity( - p.getLocation(), EntityType.ARMOR_STAND); + ArmorStand as = (ArmorStand) block.getLocation().getWorld().spawnEntity(p.getLocation(), EntityType.ARMOR_STAND); as.setGravity(false); as.setCanPickupItems(false); as.setCustomNameVisible(true); @@ -603,58 +553,67 @@ private void displayMessageHologram(Block block, String message, Player p){ as.setCustomName(SpigotPrison.format(message)); Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), as::remove, (7L * 20L)); } - + private void displayActionBarMessage(Player player, String message) { - SpigotPlayer prisonPlayer = new SpigotPlayer( player ); - Prison.get().getPlatform().showActionBar( prisonPlayer, message, 80 ); + SpigotPlayer prisonPlayer = new SpigotPlayer(player); + Prison.get().getPlatform().showActionBar(prisonPlayer, message, 80); } - + /** *

Using the ItemLoreEnables, check to see if the item in the hand has the - * specified Lore. If so, then return 100.0 if just the lore, otherwise + * specified Lore. If so, then return 100.0 if just the lore, otherwise * if it has a number to the right of the Lore, convert it to a double and * return it. *

- * - *

The only valid value to follow the lore, can only be a double number, + * + *

The only valid value to follow the lore, can only be a double number, * or an integer. For example 1.234, 50, 75.567, 99.0, or 100.0. * Any value less than 0 will be zero, which is the same as no lore (disabled). * Any value greater than 100 will be 100.0. No values following the lore will * be treated as 100.0 percent. Do not include percent sign or unit of measure. *

- * + * * @param loreEnabler * @param player * @return Percent chance of Lore enablement. */ protected double doesItemHaveAutoFeatureLore( ItemLoreEnablers loreEnabler, Player player ) { - double results = 100.0; - + double results = 0.0; + ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( player ); - if ( itemInHand.hasItemMeta() ) { + if ( itemInHand.getItemMeta() != null ) { // (itemInHand.hasItemMeta()) { NOTE: hasItemMeta() always returns nulls ItemMeta meta = itemInHand.getItemMeta(); - if ( meta.hasLore() ) { - for ( String lore : meta.getLore() ) { - if ( lore.startsWith( loreEnabler.name() )) { - String value = lore.replace( loreEnabler.name(), "" ).trim(); + if ( meta != null && meta.hasLore()) { + for (String lore : meta.getLore()) { + if (lore.startsWith( loreEnabler.name())) { + + // Lore detected so set default to 100%: + results = 100.0; - if ( value.length() > 0 ) { + String value = lore.replace( loreEnabler.name(), "" ).trim(); + + if (value.length() > 0) { + // Content has been found after the lore's name. If it is a number, then + // use that to set the lore's percentage. If it fails at parsing then use 100%. + try { results = Double.parseDouble( value ); } - catch ( NumberFormatException e ) { - + catch (NumberFormatException e) { + // Error: Default to 100% // Do not generate log messages since there will be 1000's... results = 100.0; } - + + // Clean up the parsed number. Less than zero is zero (disabled). if ( results < 0.0 ) { results = 0.0; } - + + // Cannot exceed 100% if ( results > 100.0 ) { results = 100.0; } @@ -663,360 +622,298 @@ protected double doesItemHaveAutoFeatureLore( ItemLoreEnablers loreEnabler, Play } } } - + return results; } - protected int autoFeaturePickup( BlockBreakEvent e, Player p ) { - Material brokenBlock = e.getBlock().getType(); - String blockName = brokenBlock.toString().toLowerCase(); - - ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( p ); - + protected int autoFeaturePickup( SpigotBlock block, Player p, SpigotItemStack itemInHand ) { + + +// Material brokenBlock = e.getBlock().getType(); +// String blockName = brokenBlock.toString().toLowerCase(); +// SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( p ); int count = 0; - if ( isBoolean( AutoFeatures.autoPickupAllBlocks ) ) { - count += autoPickup( true, p, itemInHand, e ); - - } - else { - - switch (blockName) { + if (isBoolean(AutoFeatures.autoPickupAllBlocks)) { + count += autoPickup( true, p, itemInHand, block ); + + } else { + + switch (block.getPrisonBlock().getBlockNameSearch() ) { + case "cobblestone": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupCobbleStone ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupCobbleStone ), p, itemInHand, block); break; - + case "stone": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupStone ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupStone ), p, itemInHand, block); break; - + case "gold_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupGoldOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupGoldOre ), p, itemInHand, block); break; - + case "iron_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupIronOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupIronOre ), p, itemInHand, block); break; - + case "coal_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupCoalOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupCoalOre ), p, itemInHand, block); break; - + case "diamond_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupDiamondOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupDiamondOre ), p, itemInHand, block); break; - + case "redstone_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupRedStoneOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupRedStoneOre ), p, itemInHand, block); break; - + case "emerald_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupEmeraldOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupEmeraldOre ), p, itemInHand, block); break; - + case "quartz_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupQuartzOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupQuartzOre ), p, itemInHand, block); break; - + case "lapis_ore": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupLapisOre ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupLapisOre ), p, itemInHand, block ); break; - + case "snow_ball": - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupSnowBall ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupSnowBall ), p, itemInHand, block ); break; - + case "glowstone_dust": // works 1.15.2 - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ) || - isBoolean( AutoFeatures.autoPickupGlowstoneDust ), - p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ) || + isBoolean( AutoFeatures.autoPickupGlowstoneDust ), p, itemInHand, block ); break; - + default: - count += autoPickup( isBoolean( AutoFeatures.autoPickupAllBlocks ), p, itemInHand, e ); + count += autoPickup(isBoolean( AutoFeatures.autoPickupAllBlocks ), p, itemInHand, block ); break; } - - } - + // Calculate XP on block break if enabled: - calculateXP( p, blockName, count ); - - -// Output.get().logInfo( "In mine: %s blockName= [%s] %s drops= %s count= %s dropNumber= %s ", + calculateXP( p, block, count ); + +// Output.get().logInfo( "In mine: %s blockName= [%s] %s drops= %s count= %s dropNumber= %s ", // mine.getName(), blockName, Integer.toString( dropNumber ), -// (e.getBlock().getDrops(itemInHand) != null ? e.getBlock().getDrops(itemInHand).size() : "-=null=-"), +// (e.getBlock().getDrops(itemInHand) != null ? e.getBlock().getDrops(itemInHand).size() : "-=null=-"), // Integer.toString( count ), Integer.toString( dropNumber ) // ); return count; } - - protected void autoFeatureSmelt( BlockBreakEvent e, Player p ) + protected void autoFeatureSmelt( SpigotBlock block, Player p, SpigotItemStack itemInHand ) { - Block block = e.getBlock(); - - autoSmelt( isBoolean( AutoFeatures.autoSmeltAllBlocks ) || isBoolean( AutoFeatures.autoSmeltGoldOre ), - "GOLD_ORE", "GOLD_INGOT", p, block ); - - autoSmelt( isBoolean( AutoFeatures.autoSmeltAllBlocks ) || isBoolean( AutoFeatures.autoSmeltIronOre ), - "IRON_ORE", "IRON_INGOT", p, block ); +// Block block = e.getBlock(); + + autoSmelt(isBoolean( AutoFeatures.autoSmeltAllBlocks ) || isBoolean( AutoFeatures.autoSmeltGoldOre ), "GOLD_ORE", "GOLD_INGOT", p, block); + + autoSmelt(isBoolean( AutoFeatures.autoSmeltAllBlocks ) || isBoolean( AutoFeatures.autoSmeltIronOre ), "IRON_ORE", "IRON_INGOT", p, block); } + protected void autoFeatureBlock( SpigotBlock block, Player p, SpigotItemStack itemInHand ) { + +// Block block = e.getBlock(); - protected void autoFeatureBlock( BlockBreakEvent e, Player p ) - { - Block block = e.getBlock(); - // Any autoBlock target could be enabled, and could have multiples of 9, so perform the - // checks within each block type's function call. So in one pass, could hit on more + // checks within each block type's function call. So in one pass, could hit on more // than one of these for multiple times too. - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockGoldBlock ), - "GOLD_INGOT", "GOLD_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockIronBlock ), - "IRON_INGOT", "IRON_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockCoalBlock ), - "COAL", "COAL_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockDiamondBlock ), - "DIAMOND", "DIAMOND_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockRedstoneBlock ), - "REDSTONE","REDSTONE_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockEmeraldBlock ), - "EMERALD", "EMERALD_BLOCK", p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockQuartzBlock ), - "QUARTZ", "QUARTZ_BLOCK", 4, p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockPrismarineBlock ), - "PRISMARINE_SHARD", "PRISMARINE", 4, p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockSnowBlock ), - "SNOW_BALL", "SNOW_BLOCK", 4, p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockGlowstone ), - "GLOWSTONE_DUST", "GLOWSTONE", 4, p, block ); - - autoBlock( isBoolean( AutoFeatures.autoBlockAllBlocks ) || - isBoolean( AutoFeatures.autoBlockLapisBlock ), - "LAPIS_LAZULI", "LAPIS_BLOCK", p, block ); + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockGoldBlock ), "GOLD_INGOT", "GOLD_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockIronBlock ), "IRON_INGOT", "IRON_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockCoalBlock ), "COAL", "COAL_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockDiamondBlock ), "DIAMOND", "DIAMOND_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockRedstoneBlock ), "REDSTONE","REDSTONE_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockEmeraldBlock ), "EMERALD", "EMERALD_BLOCK", p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockQuartzBlock ), "QUARTZ", "QUARTZ_BLOCK", 4, p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockPrismarineBlock ), "PRISMARINE_SHARD", "PRISMARINE", 4, p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockSnowBlock ), "SNOW_BALL", "SNOW_BLOCK", 4, p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockGlowstone ), "GLOWSTONE_DUST", "GLOWSTONE", 4, p, block); + + autoBlock(isBoolean( AutoFeatures.autoBlockAllBlocks ) || isBoolean( AutoFeatures.autoBlockLapisBlock ), "LAPIS_LAZULI", "LAPIS_BLOCK", p, block); } + protected void itemLoreCounter( SpigotItemStack itemInHand, String itemLore, int blocks) { + if (itemInHand.getBukkitStack().hasItemMeta()) { - protected void itemLoreCounter( ItemStack itemInHand, String itemLore, int blocks ) - { - if ( itemInHand.hasItemMeta() ) { - List lore = new ArrayList<>(); - itemLore = itemLore.trim() + " "; - itemLore = Text.translateAmpColorCodes( itemLore.trim() + " "); - + ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); + // String prisonBlockBroken = itemLore.getLore(); - - ItemMeta meta = itemInHand.getItemMeta(); - - if ( meta.hasLore() ) { + + + if (meta.hasLore()) { lore = meta.getLore(); - boolean found = false; + for( int i = 0; i < lore.size(); i++ ) { if ( lore.get( i ).startsWith( itemLore ) ) { String val = lore.get( i ).replace( itemLore, "" ).trim(); - int count = blocks; + try { - count += Integer.parseInt( val ); - } - catch ( NumberFormatException e1 ) { - Output.get().logError( "AutoManager: tool counter failure. lore= [" + - lore.get( i ) + "] val= [" + val + "] error: " + - e1.getMessage() ); } - - lore.set( i, itemLore + count ); - + count += Integer.parseInt(val); + } catch (NumberFormatException e1) { + Output.get().logError("AutoManager: tool counter failure. lore= [" + lore.get(i) + "] val= [" + val + "] error: " + e1.getMessage()); } + + lore.set(i, itemLore + count); found = true; + break; } } - + if ( !found ) { - lore.add( itemLore + 1 ); + lore.add(itemLore + 1); } - - + } else { - lore.add( itemLore + 1 ); + lore.add(itemLore + 1); } - - meta.setLore( lore ); - - itemInHand.setItemMeta( meta ); - + + meta.setLore(lore); + itemInHand.getBukkitStack().setItemMeta(meta); + // incrementCounterInName( itemInHand, meta ); - + } } - + /** *

This function will search for the loreDurabiltyResistanceName within the - * item in the hand, if found it will return the number if it exists. If not + * item in the hand, if found it will return the number if it exists. If not * found, then it will return a value of zero, indicating that no special resistance * exists, and that durability should be applied as normal. *

- * - *

If there is no value after the lore name, then the default is 100 %. + * + *

If there is no value after the lore name, then the default is 100 %. * If a value follows the lore name, then it must be an integer. * If it is less than 0, then 0. If it is greater than 100, then 100. *

- * + * * @param itemInHand * @param itemLore * @return */ - protected int getDurabilityResistance( ItemStack itemInHand, String itemLore ) { + protected int getDurabilityResistance(SpigotItemStack itemInHand, String itemLore) { int results = 0; - - if ( itemInHand.hasItemMeta() ) { - + + if ( itemInHand.getBukkitStack().hasItemMeta() ) { + List lore = new ArrayList<>(); - + itemLore = itemLore.trim() + " "; - + itemLore = Text.translateAmpColorCodes( itemLore.trim() + " "); - + // String prisonBlockBroken = itemLore.getLore(); - - ItemMeta meta = itemInHand.getItemMeta(); - - if ( meta.hasLore() ) { + + ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); + + if (meta.hasLore()) { lore = meta.getLore(); - - for( int i = 0; i < lore.size(); i++ ) { - if ( lore.get( i ).startsWith( itemLore ) ) { - + + for (String s : lore) { + if (s.startsWith(itemLore)) { + // It has the durability resistance lore, so set the results to 100. // If a value is set, then it will be replaced. results = 100; - - String val = lore.get( i ).replace( itemLore, "" ).trim(); - + + String val = s.replace(itemLore, "").trim(); + try { - results += Integer.parseInt( val ); + results += Integer.parseInt(val); + } catch (NumberFormatException e1) { + Output.get().logError("AutoManager: tool durability failure. lore= [" + s + "] val= [" + val + "] error: " + e1.getMessage()); } - catch ( NumberFormatException e1 ) { - Output.get().logError( "AutoManager: tool durability failure. lore= [" + - lore.get( i ) + "] val= [" + val + "] error: " + - e1.getMessage() ); } - + break; } } - } - + if ( results > 100d ) { results = 100; } else if ( results < 0 ) { results = 0; } - + } - + return results; } protected void incrementCounterInName( ItemStack itemInHand, ItemMeta meta ) { String name = meta.getDisplayName(); - if ( !meta.hasDisplayName() || name == null || name.trim().length() == 0 ) { + if (!meta.hasDisplayName() || name == null || name.trim().length() == 0) { name = itemInHand.getType().name().toLowerCase().replace("_", " ").trim(); name += " [1]"; } else { - - int j = name.lastIndexOf( ']' ); - if ( j == -1 ) { + + int j = name.lastIndexOf(']'); + if (j == -1) { name += " [1]"; } else { - - if ( j != -1 ) { - int i = name.lastIndexOf( '[', j ); - - if ( i != -1 ) { - String numStr = name.substring( i + 1, j ); - -// Output.get().logInfo( String.format( "AutoManager: name: %s : %s ", + if (j != -1) { + int i = name.lastIndexOf('[', j); + + if (i != -1) { + String numStr = name.substring(i + 1, j); + +// Output.get().logInfo( String.format( "AutoManager: name: %s : %s ", // name, numStr) ); - - + try { int blocksMined = Integer.parseInt( numStr ); name = name.substring( 0, i ).trim() + " [" + ++blocksMined + "]"; + } catch (NumberFormatException e1) { + Output.get().logError("AutoManager: tool counter failure. tool name= [" + name + "] error: " + e1.getMessage()); } - catch ( NumberFormatException e1 ) { - Output.get().logError( "AutoManager: tool counter failure. tool name= [" + - name + "] error: " + - e1.getMessage() ); - } - } } } - - } - if ( name != null ) { + if (name != null) { meta.setDisplayName( name ); itemInHand.setItemMeta( meta ); - } } - + /** *

This should calculate and apply the durability consumption on the tool. *

- * + * *

The damage is calculated as a value of one durability, but all damage can be * skipped if the tool has a durability enchantment. If it does, then there is a * percent chance of 1 in (1 + durabilityLevel). So if a tool has a durability level @@ -1024,94 +921,91 @@ protected void incrementCounterInName( ItemStack itemInHand, ItemMeta meta ) { * a 75% chance. And a level of 9 has a 90% chance. There are no upper limits on * durability enchantment levels. *

- * + * *

Some blocks may have a damage of greater than 1, but for now, this - * does not take that in to consideration. If hooking up in the future, just + * does not take that in to consideration. If hooking up in the future, just * set the initial damage to the correct value based upon block type that was mined. *

- * + * *

The parameter durabilityResistance is optional, to disable use a value of ZERO. * This is a percentage and is calculated first. If random value is equal to the parameter * or less, then it will skip the durability calculations for the current event. *

- * + * *

Based upon the following URL. See Tool Durability. *

* https://minecraft.gamepedia.com/Item_durability - * + * * @param player * @param itemInHand - Should be the tool they used to mine or dig the block - * @param durabilityResistance - Chance to prevent durability wear being applied. + * @param durabilityResistance - Chance to prevent durability wear being applied. * Zero always disables this calculation and allows normal durability calculations * to be performed. 100 always prevents wear. */ - protected void calculateDurability( Player player, ItemStack itemInHand, int durabilityResistance ) { + protected void calculateDurability(Player player, SpigotItemStack itemInHand, int durabilityResistance) { + short damage = 1; // Generally 1 unless instant break block then zero. if ( durabilityResistance >= 100 ) { damage = 0; - } - else if ( durabilityResistance > 0 ) { - + } else if ( durabilityResistance > 0 ) { if ( getRandom().nextInt( 100 ) <= durabilityResistance ) { damage = 0; } } - - if ( damage > 0 && itemInHand.containsEnchantment( Enchantment.DURABILITY ) ) { - int durabilityLevel = itemInHand.getEnchantmentLevel( Enchantment.DURABILITY ); + + if (damage > 0 && itemInHand.getBukkitStack().containsEnchantment( Enchantment.DURABILITY)) { + int durabilityLevel = itemInHand.getBukkitStack().getEnchantmentLevel( Enchantment.DURABILITY ); // the chance of losing durability is 1 in (1+level) // So if the random int == 0, then take damage, otherwise none. - if ( getRandom().nextInt( durabilityLevel ) > 0 ) { + if (getRandom().nextInt( durabilityLevel ) > 0) { damage = 0; } } - - if ( damage > 0 ) { + + if (damage > 0) { + Compatibility compat = SpigotPrison.getInstance().getCompatibility(); - int maxDurability = compat.getDurabilityMax( itemInHand ); - - int durability = compat.getDurability( itemInHand );; - + int durability = compat.getDurability( itemInHand ); int newDurability = durability + damage; - - if ( newDurability > maxDurability ) { + + if (newDurability > maxDurability) { // Item breaks! ;( compat.breakItemInMainHand( player ); - } - else { + } else { compat.setDurability( itemInHand, newDurability ); } - player.updateInventory(); - } } - - private void calculateXP( Player player, String blockName, int count ) { - - if ( isBoolean( AutoFeatures.isCalculateXPEnabled )) { - - int xp = 0; - for ( int i = 0; i < count; i++ ) { - xp += calculateXP( blockName ); - } - - if ( xp > 0 ) { - - if ( isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )) { - - Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); - - ((ExperienceOrb) player.getWorld().spawn(dropPoint, ExperienceOrb.class)).setExperience(xp); + + private void calculateXP(Player player, SpigotBlock block, int count) { + + if (isBoolean(AutoFeatures.isCalculateXPEnabled) && block != null ) { + + String blockName = block.getPrisonBlock() == null ? null : block.getPrisonBlock().getBlockName(); + + if ( blockName != null ) { + + int xp = 0; + for ( int i = 0; i < count; i++ ) { + xp += calculateXP( blockName ); } - else { - - player.giveExp( xp ); + + if (xp > 0) { + + if ( isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )) { + + Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); + ((ExperienceOrb) player.getWorld().spawn(dropPoint, ExperienceOrb.class)).setExperience(xp); + + } + else { + player.giveExp( xp ); + } } - } } } @@ -1119,7 +1013,7 @@ private void calculateXP( Player player, String blockName, int count ) { *

This calculate xp based upon the block that is broken. * Fortune does not increase XP that a block drops. *

- * + * *
    *
  • Coal Ore: 0 - 2
  • *
  • Nether Gold Ore: 0 - 1
  • @@ -1128,37 +1022,36 @@ private void calculateXP( Player player, String blockName, int count ) { *
  • Redstone Ore: 1 - 5
  • *
  • Monster Spawner: 15 - 43
  • *
- * + * * @param Block * @return */ private int calculateXP( String blockName ) { int xp = 0; - - switch ( blockName.toLowerCase() ) - { + + switch (blockName.toLowerCase()) { case "coal_ore": xp = getRandom().nextInt( 2 ); break; - + case "nether_gold_ore": xp = getRandom().nextInt( 1 ); break; - + case "diamond_ore": case "emerald_ore": xp = getRandom().nextInt( 4 ) + 3; break; - + case "lapis_ore": case "nether_quartz_ore": xp = getRandom().nextInt( 3 ) + 2; break; - + case "redstone_ore": xp = getRandom().nextInt( 4 ) + 1; break; - + case "spawn": xp = getRandom().nextInt( 28 ) + 15; break; @@ -1166,129 +1059,123 @@ private int calculateXP( String blockName ) { default: break; } - + return xp; } - + /** - *

This function is based upon the following wiki page. + *

This function is based upon the following wiki page. *

* https://minecraft.gamepedia.com/Fortune - * - *

"Ore: For coal ore, diamond ore, emerald ore, lapis lazuli ore, - * nether gold ore,‌[upcoming: JE 1.16] and nether quartz ore, - * Fortune I gives a 33% chance to multiply drops by 2 (averaging 33% increase), - * Fortune II gives a chance to multiply drops by 2 or 3 (25% chance each, - * averaging 75% increase), and Fortune III gives a chance to multiply drops + * + *

"Ore: For coal ore, diamond ore, emerald ore, lapis lazuli ore, + * nether gold ore,‌[upcoming: JE 1.16] and nether quartz ore, + * Fortune I gives a 33% chance to multiply drops by 2 (averaging 33% increase), + * Fortune II gives a chance to multiply drops by 2 or 3 (25% chance each, + * averaging 75% increase), and Fortune III gives a chance to multiply drops * by 2, 3, or 4 (20% chance each, averaging 120% increase). *

- *

"Generally speaking, Fortune gives a weight of 2 to a normal drop chance - * and adds a weight of 1 for each extra drop multiplier. The drop multipliers + *

"Generally speaking, Fortune gives a weight of 2 to a normal drop chance + * and adds a weight of 1 for each extra drop multiplier. The drop multipliers * are the integers between 2 and Fortune Level + 1, inclusive. *

- *

"The formula to calculate the average drops multiplier is - * 1/(Fortune Level+2) + (Fortune Level+1)/2, which means - * Fortune IV gives 2.67x drops on average, Fortune V gives + *

"The formula to calculate the average drops multiplier is + * 1/(Fortune Level+2) + (Fortune Level+1)/2, which means + * Fortune IV gives 2.67x drops on average, Fortune V gives * 3.14x drops on average, etc. " *

- * - *

Discrete random Glowstone, melons, nether wart, redstone ore, - * sea lanterns, and sweet berries use a discrete uniform distribution, - * meaning each possible drop amount is equally likely to be dropped. - * Fortune increases the maximum number of drops by 1 per level. However, - * maximum drop limitations may apply: glowstone has a cap of 4 glowstone - * dust, sea lanterns have a cap of 5 prismarine crystals, and melons have - * a cap of 9 melon slices. If a drop higher than these maximums is rolled, - * it is rounded down to the cap. + * + *

Discrete random Glowstone, melons, nether wart, redstone ore, + * sea lanterns, and sweet berries use a discrete uniform distribution, + * meaning each possible drop amount is equally likely to be dropped. + * Fortune increases the maximum number of drops by 1 per level. However, + * maximum drop limitations may apply: glowstone has a cap of 4 glowstone + * dust, sea lanterns have a cap of 5 prismarine crystals, and melons have + * a cap of 9 melon slices. If a drop higher than these maximums is rolled, + * it is rounded down to the cap. *

- * - * + * + * * @param blocks * @param fortuneLevel */ - protected void calculateFortune( ItemStack blocks, int fortuneLevel ) { - - if ( fortuneLevel > 0 ) { + protected void calculateFortune(SpigotItemStack blocks, int fortuneLevel) { + + if (fortuneLevel > 0) { + int count = blocks.getAmount(); - int multiplier = 1; - - - // Due to variations with gold and wood PickAxe need to use a dynamic + + // Due to variations with gold and wood PickAxe need to use a dynamic // Material name selection which will fit for the version of MC that is // being ran. - Material block = blocks.getType(); - - if ( block == Material.COAL || - block == Material.DIAMOND || - block == Material.EMERALD || - block == Material.LAPIS_BLOCK || - block == Material.GOLD_BLOCK || - block == Material.QUARTZ_BLOCK || - block == Material.COAL_ORE || - block == Material.DIAMOND_ORE || - block == Material.EMERALD_ORE || - block == Material.LAPIS_ORE || - block == Material.GOLD_ORE || - block == Material.matchMaterial( "QUARTZ_ORE" ) ) { - + BlockType block = blocks.getMaterial(); + + if (block == BlockType.COAL || + block == BlockType.DIAMOND || + block == BlockType.EMERALD || + block == BlockType.LAPIS_BLOCK || + block == BlockType.GOLD_BLOCK || + block == BlockType.QUARTZ_BLOCK || + block == BlockType.COAL_ORE || + block == BlockType.DIAMOND_ORE || + block == BlockType.EMERALD_ORE || + block == BlockType.LAPIS_ORE || + block == BlockType.GOLD_ORE || + block == BlockType.NETHER_QUARTZ_ORE) { + multiplier = calculateFortuneMultiplier( fortuneLevel, multiplier ); - + // multiply the multiplier: count *= multiplier; - } - else if ( block == Material.GLOWSTONE || - block == Material.GLOWSTONE_DUST || - block == Material.REDSTONE || - block == Material.SEA_LANTERN || - block == Material.matchMaterial( "GLOWING_REDSTONE_ORE" ) || - block == Material.PRISMARINE || - - block == Material.matchMaterial( "BEETROOT_SEEDS" ) || - block == Material.CARROT || - block == Material.MELON || - block == Material.MELON_SEEDS || - block == Material.matchMaterial( "NETHER_WARTS" ) || - block == Material.POTATO || - block == Material.GRASS || - block == Material.WHEAT ) { + } else if ( block == BlockType.GLOWSTONE || + block == BlockType.GLOWSTONE_DUST || + block == BlockType.REDSTONE || + block == BlockType.SEA_LANTERN || + block == BlockType.GLOWING_REDSTONE_ORE || + block == BlockType.PRISMARINE || + + block == BlockType.BEETROOT_SEEDS || + block == BlockType.CARROT || + block == BlockType.MELON || + block == BlockType.MELON_SEEDS || + block == BlockType.NETHER_WART || + block == BlockType.POTATO || + block == BlockType.GRASS || + block == BlockType.WHEAT ) { multiplier = getRandom().nextInt( fortuneLevel ); - + // limits slightly greater than standard: - if ( block == Material.GLOWSTONE ) { + if (block == BlockType.GLOWSTONE) { // standard: 4 - if ( multiplier > 5 ) { + if (multiplier > 5) { multiplier = 5; } - } - else if ( block == Material.SEA_LANTERN ) { + } else if (block == BlockType.SEA_LANTERN) { // standard: 5 - if ( multiplier > 6 ) { + if (multiplier > 6) { multiplier = 6; } - } - else if ( block == Material.MELON ) { + } else if (block == BlockType.MELON) { // standard: 9 - if ( multiplier > 11 ) { + if (multiplier > 11) { multiplier = 11; } } - + // add the multiplier to the count: count += multiplier; - } - + // The count has the final value so set it as the amount: blocks.setAmount( count ); - } - - - + + + // cannot use switches with dynamic Material types: // switch ( blocks.getType() ){ -// +// // case COAL: // case DIAMOND: // case EMERALD: @@ -1301,9 +1188,9 @@ else if ( block == Material.MELON ) { // case LAPIS_ORE: // case GOLD_ORE: // case QUARTZ_ORE: -// +// // multiplier = calculateFortuneMultiplier( fortuneLevel, multiplier ); -// +// // // multiply the multiplier: // count *= multiplier; // break; @@ -1323,9 +1210,9 @@ else if ( block == Material.MELON ) { // case POTATO: // case GRASS: // case WHEAT: -// +// // multiplier = getRandom().nextInt( fortuneLevel ); -// +// // switch ( blocks.getType() ) // { // // limits slightly greater than standard: @@ -1350,85 +1237,83 @@ else if ( block == Material.MELON ) { // default: // break; // } -// +// // // add the multiplier to the count: // count += multiplier; -// +// // default: // break; // } - + // // The count has the final value so set it as the amount: // blocks.setAmount( count ); } - private int calculateFortuneMultiplier( int fortuneLevel, int multiplier ) - { + private int calculateFortuneMultiplier(int fortuneLevel, int multiplier) { int rnd = getRandom().nextInt( 100 ); - switch ( fortuneLevel ) - { + switch (fortuneLevel) { case 0: break; case 1: - if ( rnd <= 33 ) { + if (rnd <= 33) { multiplier = 2; } break; - + case 2: - if ( rnd <= 25 ) { + if (rnd <= 25) { multiplier = 2; } - else if ( rnd <= 50 ) { + else if (rnd <= 50) { multiplier = 3; } break; - - case 3: - if ( rnd <= 20 ) { + + case 3: + if (rnd <= 20) { multiplier = 2; } - else if ( rnd <= 40 ) { + else if (rnd <= 40) { multiplier = 3; } - else if ( rnd <= 60 ) { + else if (rnd <= 60) { multiplier = 4; } break; - - - case 4: - if ( rnd <= 16 ) { + + + case 4: + if (rnd <= 16) { multiplier = 2; } - else if ( rnd <= 32 ) { + else if (rnd <= 32) { multiplier = 3; } - else if ( rnd <= 48 ) { + else if (rnd <= 48) { multiplier = 4; } - else if ( rnd <= 64 ) { + else if (rnd <= 64) { multiplier = 5; } break; - + default: // values of 5 or higher - if ( rnd <= 16 ) { + if (rnd <= 16) { multiplier = 2; } - else if ( rnd <= 32 ) { + else if (rnd <= 32) { multiplier = 3; } - else if ( rnd <= 48 ) { + else if (rnd <= 48) { multiplier = 4; } - else if ( rnd <= 64 ) { + else if (rnd <= 64) { multiplier = 5; } - else if ( rnd <= 74 ) { + else if (rnd <= 74) { // Only 8% not 16% chance multiplier = 6; } @@ -1436,95 +1321,91 @@ else if ( rnd <= 74 ) { } return multiplier; } - + /** - *

This function has yet to be implemented, but it should implement behavior if + *

This function has yet to be implemented, but it should implement behavior if * silk touch is enabled for the tool. *

- * + * * @param itemInHand * @param drops */ @SuppressWarnings( "unused" ) - private void calculateSilkTouch( ItemStack itemInHand, Collection drops ) { - - for ( ItemStack itemStack : drops ) { - + private void calculateSilkTouch(SpigotItemStack itemInHand, Collection drops) { + + for (SpigotItemStack itemStack : drops) { + // If stack is gravel, then there is a 10% chance of droping flint. - + } - } - + /** *

Because of the use of getDrops() function, not all of the correct drops are actually - * dropped. This function tries to restore some of those special drops. + * dropped. This function tries to restore some of those special drops. *

- * - *

Example of what this does, is to provide a random drop of flint when mining + * + *

Example of what this does, is to provide a random drop of flint when mining * coal ore. *

- * - *

"When a block of gravel is mined, there is a 10% chance for a single piece of flint - * to drop instead of the gravel block. When mined with a Fortune-enchanted tool, this chance - * increases to 14% at Fortune I, 25% at Fortune II, and 100% at Fortune III. Gravel mined - * using a tool with Silk Touch or gravel that fell on a non-solid block never produces flint." + * + *

"When a block of gravel is mined, there is a 10% chance for a single piece of flint + * to drop instead of the gravel block. When mined with a Fortune-enchanted tool, this chance + * increases to 14% at Fortune I, 25% at Fortune II, and 100% at Fortune III. Gravel mined + * using a tool with Silk Touch or gravel that fell on a non-solid block never produces flint." * wiki *

- * + * *

For example gravel having random flint drops. *

- * + * * @param itemInHand * @param drops */ - private void calculateDropAdditions( ItemStack itemInHand, Collection drops ) { - - for ( ItemStack itemStack : drops ) { - + private void calculateDropAdditions(SpigotItemStack itemInHand, Collection drops) { + + for (SpigotItemStack itemStack : drops) { + // If gravel and has the 10% chance whereas rnd is zero, which is 1 out of 10. // But if has silk touch, then never drop flint. calculateDropAdditionsGravelFlint( itemInHand, itemStack, drops ); - } - } /** *

For gravel flint drops, this function adds special processing to increase the quantity - * of flint drops from the standard 1, to be influence by fortune enchants. If fortune + * of flint drops from the standard 1, to be influence by fortune enchants. If fortune * is >= 3, then add one to the quantity drop, plus a random chance to add floor(fortune / 5). * So if fortune is 3, then the drop will always be 2. If fortune is 5, then drop will * be 2, plus a random chance of one additional drop. If fortune is 20, then drop will be - * 2, plus an equal random chance to add 0 to 4 additional flints to the quantity of + * 2, plus an equal random chance to add 0 to 4 additional flints to the quantity of * the flint drop. The other thing that is different from vanilla, is that if the player * will get a flint drop, they will still get the normal gravel drop. *

- * + * * @param itemInHand * @param itemStack * @param drops */ - private void calculateDropAdditionsGravelFlint( ItemStack itemInHand, - ItemStack itemStack, Collection drops ) { - if ( itemStack.getType() == Material.GRAVEL && - !hasSilkTouch( itemInHand ) ) { - + private void calculateDropAdditionsGravelFlint(SpigotItemStack itemInHand, SpigotItemStack itemStack, + Collection drops ) { + if (itemStack.getMaterial() == BlockType.GRAVEL && !hasSilkTouch(itemInHand)) { + int quantity = 1; int threshold = 10; - + // If fortune is enabled on the tool, then increase drop oddds by: // 1 = 14%, 2 = 25%, 3+ = 100% - int fortune = getFortune( itemInHand ); - switch ( fortune ) { + int fortune = getFortune(itemInHand); + switch (fortune) { case 0: // No additional threshold when fortune is zero: break; case 1: threshold = 14; break; - case 2: + case 2: threshold = 25; break; case 3: @@ -1533,163 +1414,25 @@ private void calculateDropAdditionsGravelFlint( ItemStack itemInHand, threshold = 100; break; } - + // If zero, then 10% chance of 1 out of 10. - if ( getRandom().nextInt( 100 ) <= threshold ) { - - // If fortune is >= 3, then add one to the quantity drop, plus a + if (getRandom().nextInt(100) <= threshold) { + + // If fortune is >= 3, then add one to the quantity drop, plus a // random chance to add floor(fortune / 5). - if ( fortune >= 3 ) { - quantity += 1 + getRandom().nextInt( Math.floorDiv( fortune, 5 ) ); + if (fortune >= 3) { + quantity += 1 + getRandom().nextInt(Math.floorDiv( fortune, 5)); } - - ItemStack flintStack = new ItemStack( Material.FLINT, quantity ); - drops.add( flintStack ); + +// ItemStack flintStack = new ItemStack(Material.FLINT, quantity); + SpigotItemStack flintStack = new SpigotItemStack( quantity, BlockType.FLINT); + drops.add(flintStack); } } } - + public Random getRandom() { return random; } -// public boolean isAutoManagerEnabled() { -// return isAutoManagerEnabled; -// } - -// public boolean isDropItemsIfInventoryIsFull() { -// return dropItemsIfInventoryIsFull; -// } - -// public boolean isPlaySoundIfInventoryIsFull() { -// return playSoundIfInventoryIsFull; -// } - -// public boolean isHologramIfInventoryIsFull() { -// return hologramIfInventoryIsFull; -// } - -// public boolean isAutoPickupEnabled() { -// return autoPickupEnabled; -// } -// -// public boolean isAutoPickupAllBlocks() { -// return autoPickupAllBlocks; -// } - -// public boolean isAutoPickupCobbleStone() { -// return autoPickupCobbleStone; -// } -// -// public boolean isAutoPickupStone() { -// return autoPickupStone; -// } -// -// public boolean isAutoPickupGoldOre() { -// return autoPickupGoldOre; -// } -// -// public boolean isAutoPickupIronOre() { -// return autoPickupIronOre; -// } -// -// public boolean isAutoPickupCoalOre() { -// return autoPickupCoalOre; -// } -// -// public boolean isAutoPickupDiamondOre() { -// return autoPickupDiamondOre; -// } -// -// public boolean isAutoPickupRedstoneOre() { -// return autoPickupRedstoneOre; -// } -// -// public boolean isAutoPickupEmeraldOre() { -// return autoPickupEmeraldOre; -// } -// -// public boolean isAutoPickupQuartzOre() { -// return autoPickupQuartzOre; -// } -// -// public boolean isAutoPickupLapisOre() { -// return autoPickupLapisOre; -// } -// -// public boolean isAutoPickupSnowBall() { -// return autoPickupSnowBall; -// } -// -// public boolean isAutoPickupGlowstoneDust() { -// return autoPickupGlowstoneDust; -// } - -// public boolean isAutoSmeltEnabled() { -// return autoSmeltEnabled; -// } - -// public boolean isAutoSmeltAllBlocks() { -// return autoSmeltAllBlocks; -// } -// -// public boolean isAutoSmeltGoldOre() { -// return autoSmeltGoldOre; -// } -// -// public boolean isAutoSmeltIronOre() { -// return autoSmeltIronOre; -// } - -// public boolean isAutoBlockEnabled() { -// return autoBlockEnabled; -// } -// -// public boolean isAutoBlockAllBlocks() { -// return autoBlockAllBlocks; -// } - -// public boolean isAutoBlockGoldBlock() { -// return autoBlockGoldBlock; -// } -// -// public boolean isAutoBlockIronBlock() { -// return autoBlockIronBlock; -// } -// -// public boolean isAutoBlockCoalBlock() { -// return autoBlockCoalBlock; -// } -// -// public boolean isAutoBlockDiamondBlock() { -// return autoBlockDiamondBlock; -// } -// -// public boolean isAutoBlockRedstoneBlock() { -// return autoBlockRedstoneBlock; -// } -// -// public boolean isAutoBlockEmeraldBlock() { -// return autoBlockEmeraldBlock; -// } -// -// public boolean isAutoBlockQuartzBlock() { -// return autoBlockQuartzBlock; -// } -// -// public boolean isAutoBlockPrismarineBlock() { -// return autoBlockPrismarineBlock; -// } -// -// public boolean isAutoBlockLapisBlock() { -// return autoBlockLapisBlock; -// } -// -// public boolean isAutoBlockSnowBlock() { -// return autoBlockSnowBlock; -// } -// -// public boolean isAutoBlockGlowstone() { -// return autoBlockGlowstone; -// } -} +} \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java index f0dcff45d..8488ae498 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java @@ -15,7 +15,9 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.spigot.game.SpigotPlayer; /** *

This is a pivotal class that "monitors" onBlockBreak events so it can @@ -149,13 +151,28 @@ public void onTEBlockExplode(TEBlockExplodeEvent e) { genericBlockExplodeEvent( e ); } - private void genericBlockEvent( BlockBreakEvent e ) { + /** + *

This genericBlockEvent handles the basics of a BlockBreakEvent to see if it has happened + * within a mine or not. If it is happening within a mine, then we process it with the doAction() + * function. + *

+ * + *

For this class only. the doAction() is only counting the block break event, but does + * nothing with the actual block such that there is no need to have knowledge as to if + * it is a custom block. In other doAction() functions that would exist in other classes + * that extend from this one, it may need that information. The hooks to find the custom + * blocks is within the Block's getPrisonBlock() function. + *

+ * + * @param e + */ + protected void genericBlockEvent( BlockBreakEvent e ) { // Fast fail: If the prison's mine manager is not loaded, then no point in processing anything. - if ( getPrisonMineManager() != null ) { + if ( getPrisonMineManager() != null ) + { // long startNano = System.nanoTime(); - boolean isAir = e.getBlock().getType() != null && e.getBlock().getType() == Material.AIR; // If canceled it must be AIR, otherwise if it is not canceled then @@ -183,8 +200,16 @@ private void genericBlockEvent( BlockBreakEvent e ) { // This is where the processing actually happens: if ( mine != null ) { - doAction( mine, e ); + + // Set the mine's PrisonBlockTypes for the block. Used to identify custom blocks. + // Needed since processing of the block will lose track of which mine it came from. + block.setPrisonBlockTypes( mine.getPrisonBlockTypes() ); + + doAction( block, mine, e ); } + + // future change to allow auto features outside of mines: +// doAction( block, mine, e ); } // for debug use: Uncomment to use. @@ -208,7 +233,7 @@ private void genericBlockEvent( BlockBreakEvent e ) { * * @param e */ - private void genericBlockExplodeEvent( TEBlockExplodeEvent e ) + protected void genericBlockExplodeEvent( TEBlockExplodeEvent e ) { // Fast fail: If the prison's mine manager is not loaded, then no point in processing anything. if ( getPrisonMineManager() != null ) { @@ -282,27 +307,42 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e ) } - public void doAction( Mine mine, BlockBreakEvent e ) { - mine.incrementBlockBreakCount(); - mine.incrementTotalBlocksMined(); - - // Other possible processing: - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); + public void doAction( SpigotBlock block, Mine mine, BlockBreakEvent e ) { + if ( mine != null ) { + + mine.incrementBlockBreakCount(); + mine.incrementTotalBlocksMined(); + + // Other possible processing: + + // Process mine block break events: + SpigotPlayer player = new SpigotPlayer( e.getPlayer() ); + mine.processBlockBreakEventCommands( 1, player, BlockEventType.eventBlockBreak ); + + + // Checks to see if the mine ran out of blocks, and if it did, then + // it will reset the mine: + mine.checkZeroBlockReset(); + } } public void doAction( Mine mine, TEBlockExplodeEvent e, int blockCount ) { - - mine.addBlockBreakCount( blockCount ); - mine.addTotalBlocksMined( blockCount ); - - // Other possible processing: - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); + if ( mine != null ) { + + mine.addBlockBreakCount( blockCount ); + mine.addTotalBlocksMined( blockCount ); + + // Other possible processing: + + // Process mine block break events: + SpigotPlayer player = new SpigotPlayer( e.getPlayer() ); + mine.processBlockBreakEventCommands( blockCount, player, BlockEventType.eventTEXplosion ); + + + // Checks to see if the mine ran out of blocks, and if it did, then + // it will reset the mine: + mine.checkZeroBlockReset(); + } } private Mine findMineLocation( SpigotBlock block ) { @@ -332,7 +372,7 @@ private TreeMap getPlayerCache() { return getPrisonMineManager().getPlayerCache(); } - private PrisonMines getPrisonMineManager() { + public PrisonMines getPrisonMineManager() { if ( prisonMineManager == null && !isMineModuleDisabled() ) { Optional mmOptional = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); if ( mmOptional.isPresent() && mmOptional.get().isEnabled() ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index b700e7cb4..be672f3d7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -19,13 +19,19 @@ package tech.mcprison.prison.spigot.block; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.integration.CustomBlockIntegration; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.internal.block.BlockState; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.util.BlockType; @@ -38,8 +44,19 @@ public class SpigotBlock implements Block { private org.bukkit.block.Block bBlock; + /** + * If this block was identified as being within a specific mine, then + * keep track of the mine's PrisonBlockTypes to ensure the + * correct custom block integration is able to identify it if it + * is a custom block type. + */ + private transient Set prisonBlockTypes; + + public SpigotBlock(org.bukkit.block.Block bBlock) { this.bBlock = bBlock; + + this.prisonBlockTypes = new HashSet<>(); } @Override public Location getLocation() { @@ -60,13 +77,97 @@ public SpigotBlock(org.bukkit.block.Block bBlock) { @Override public PrisonBlock getPrisonBlock() { - return SpigotPrison.getInstance().getCompatibility().getPrisonBlock( bBlock ); + PrisonBlock results = null; + + if ( getPrisonBlockTypes() != null ) { + + // Need to see if any PrisonBlockTypes exist in the mine where this block is located. + for ( PrisonBlockType blockType : getPrisonBlockTypes() ) { + + results = getPrisonBlockFromCustomBlockIntegration( blockType ); + if ( results != null ) { + break; + } + } + } + + if ( results == null ) { + results = SpigotPrison.getInstance().getCompatibility().getPrisonBlock( bBlock ); + } + return results; } - public void setPrisonBlock( PrisonBlock prisonBlock ) { - SpigotPrison.getInstance().getCompatibility(). - updateSpigotBlock( prisonBlock, bBlock ); + private PrisonBlock getPrisonBlockFromCustomBlockIntegration( PrisonBlockType blockType ) { + PrisonBlock results = null; + + switch ( blockType ) + { + case minecraft: + // No special processing for minecraft types since that will be the fallback later on: + + case CustomItems: + { + CustomBlockIntegration customItemsIntegration = + PrisonAPI.getIntegrationManager().getCustomBlockIntegration( blockType ); + // NOTE: This would be the situation where the admin added the Custom Items plugin, added blocks + // then removed the plugin. So if it's null, ignore it. + if ( customItemsIntegration != null ) { + results = customItemsIntegration.getCustomBlock( this ); + } + } + + break; + + default: + break; + } + + return results; + } + + + public Set getPrisonBlockTypes() { + return prisonBlockTypes; + } + public void setPrisonBlockTypes( Set prisonBlockTypes ) { + this.prisonBlockTypes = prisonBlockTypes; + } + + public void setPrisonBlock( PrisonBlock prisonBlock ) { + + switch ( prisonBlock.getBlockType() ) + { + case minecraft: + { + SpigotPrison.getInstance().getCompatibility(). + updateSpigotBlock( prisonBlock, bBlock ); + } + + + break; + + case CustomItems: + { + CustomBlockIntegration customItemsIntegration = + PrisonAPI.getIntegrationManager().getCustomBlockIntegration( prisonBlock.getBlockType() ); + + Block results = customItemsIntegration.setCustomBlockId( this, prisonBlock.getBlockName(), false ); + if ( results != null ) { + this.bBlock = ((SpigotBlock) results).getWrapper(); + } + else { + Output.get().logInfo( "SpigotBLock.setPrisonBlock: Failed to set a custom block %s ", prisonBlock.getBlockNameFormal() ); + } + } + + break; + + default: + break; + } + + } public void setBlockFace( BlockFace blockFace ) { @@ -168,7 +269,9 @@ public void setType(BlockType blockType) { return ret; } - @Override public List getDrops(ItemStack tool) { + + @Override + public List getDrops(ItemStack tool) { List ret = new ArrayList<>(); bBlock.getDrops(SpigotUtil.prisonItemStackToBukkit(tool)) @@ -176,9 +279,19 @@ public void setType(BlockType blockType) { return ret; } + +// public List getDrops(SpigotItemStack tool) { +// List ret = new ArrayList<>(); +// +// bBlock.getDrops(SpigotUtil.prisonItemStackToBukkit(tool)) +// .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); +// +// return ret; +// } public org.bukkit.block.Block getWrapper() { return bBlock; } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java new file mode 100644 index 000000000..3db67c05a --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java @@ -0,0 +1,82 @@ +package tech.mcprison.prison.spigot.block; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; + +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.util.BlockType; + +public class SpigotItemStack + extends ItemStack { + + private org.bukkit.inventory.ItemStack bukkitStack; + + public SpigotItemStack( org.bukkit.inventory.ItemStack bukkitStack ) { + super(); + + this.bukkitStack = bukkitStack; + + if (bukkitStack == null || bukkitStack.getType().equals(Material.AIR)) { + setAmount( 0 ); + setMaterial( BlockType.AIR ); + } + else { + + ItemMeta meta; + if (!bukkitStack.hasItemMeta()) { + meta = Bukkit.getItemFactory().getItemMeta(bukkitStack.getType()); + } else { + meta = bukkitStack.getItemMeta(); + } + + String displayName = null; + + if (meta.hasDisplayName()) { + displayName = meta.getDisplayName(); + } + + int amount = bukkitStack.getAmount(); + + BlockType type = SpigotPrison.getInstance().getCompatibility() + .getBlockType( bukkitStack ); +// BlockType type = materialToBlockType(bukkitStack.getType()); + + List lores = new ArrayList<>(); + + if ( meta.hasLore() ) { + for ( String lore : meta.getLore() ) { + lores.add( lore ); + } + } + + setDisplayName( displayName ); + setAmount( amount ); + setMaterial( type ); + setLore( lores ); + } + + + } + + public SpigotItemStack(String displayName, int amount, BlockType material, String... lore) { + super(displayName, amount, material, lore ); + } + + public SpigotItemStack(int amount, BlockType material, String... lore) { + super( amount, material, lore ); + } + + + public org.bukkit.inventory.ItemStack getBukkitStack() { + return bukkitStack; + } + + public void setBukkitStack( org.bukkit.inventory.ItemStack bukkitStack ) { + this.bukkitStack = bukkitStack; + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java index 783b61462..107f24740 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java @@ -7,6 +7,9 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.game.SpigotCommandSender; +/** + * @author RoyalBlueRanger + */ public class PrisonSpigotBaseCommands { private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); @@ -18,9 +21,8 @@ public Configuration getMessages() { protected boolean isConfig( String configId ) { String config = getConfig().getString( configId ); - boolean results = config != null && config.equalsIgnoreCase( "true" ); - - return results; + + return config != null && config.equalsIgnoreCase( "true" ); } protected boolean isPrisonConfig( String configId ) { @@ -31,21 +33,17 @@ protected boolean isPrisonConfig( String configId ) { protected String getConfig( String configId ) { String config = getConfig().getString( configId ); - + return config == null ? "" : config; } protected String getPrisonConfig( String configId ) { - - String config = SpigotPrison.getInstance().getConfig().getString( configId ); - - return config; + return SpigotPrison.getInstance().getConfig().getString( configId ); } protected Configuration getConfig() { - Configuration guiConfig = SpigotPrison.getInstance().getGuiConfig(); - return guiConfig; + return SpigotPrison.getInstance().getGuiConfig(); } protected Player getSpigotPlayer( CommandSender sender ) { @@ -60,6 +58,5 @@ protected Player getSpigotPlayer( CommandSender sender ) { } return player; } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotCommands.java index 596a82667..46454fc66 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotCommands.java @@ -11,20 +11,18 @@ * @author GABRYCA * @author RoyalBlueRanger */ -public class PrisonSpigotCommands - extends PrisonSpigotBaseCommands - implements Listener { +public class PrisonSpigotCommands extends PrisonSpigotBaseCommands implements Listener { /** * NOTE: onlyPlayers needs to be false so players can use /gui help on the command, even from console. * * @param sender */ - @Command( identifier = "gui", description = "The GUI", + @Command( identifier = "gui", description = "The Prison's GUI", aliases = {"prisonmanager gui", "gui admin"}, permissions = {"prison.admin", "prison.prisonmanagergui"}, onlyPlayers = false - ) + ) private void prisonManagerGUI(CommandSender sender) { Player player = getSpigotPlayer(sender); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java index 5e1a0e34c..2d1e327b0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java @@ -6,6 +6,9 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.spigot.gui.mine.SpigotPlayerMinesGUI; +/** + * @author RoyalBlueRanger + */ public class PrisonSpigotMinesCommands extends PrisonSpigotBaseCommands { @@ -15,7 +18,10 @@ public void minesGUICommand(CommandSender sender) { if (!sender.hasPermission("mines.admin") && isPrisonConfig("mines-gui-enabled") ) { prisonManagerMines( sender ); -// sender.dispatchCommand("gui mines"); + + if (isPrisonConfig("prison-gui-enabled") && isConfig("Options.Mines.GUI_Enabled")){ + sender.dispatchCommand("gui mines"); + } } else { sender.dispatchCommand("mines help"); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java index 9b066c1df..b2b1b27d2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java @@ -16,15 +16,18 @@ import tech.mcprison.prison.spigot.gui.rank.SpigotConfirmPrestigeGUI; import tech.mcprison.prison.spigot.gui.rank.SpigotPlayerPrestigesGUI; +/** + * @author RoyalBlueRanger + */ public class PrisonSpigotPrestigeCommands extends PrisonSpigotBaseCommands { private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); - @Command(identifier = "prestiges", onlyPlayers = true, altPermissions = {"-none-", "prison.admin"}) + @Command(identifier = "prestiges", onlyPlayers = true) public void prestigesGUICommand(CommandSender sender) { - if ( !isPrisonConfig( "prestiges") ) { + if ( !isPrisonConfig( "prestiges") && !isPrisonConfig( "prestige.enabled" ) ) { sender.sendMessage(SpigotPrison.format(messages.getString("Message.PrestigesDisabledDefault"))); return; } @@ -37,22 +40,19 @@ public void prestigesGUICommand(CommandSender sender) { } } - - @Command(identifier = "prestige", onlyPlayers = true, altPermissions = "-none-") + @Command(identifier = "prestige", onlyPlayers = true) public void prestigesPrestigeCommand(CommandSender sender) { - if ( isPrisonConfig( "prestiges" ) ) { - sender.dispatchCommand("gui prestige"); + if ( isPrisonConfig( "prestiges" ) || isPrisonConfig( "prestige.enabled" ) ) { + sender.dispatchCommand("rankup prestiges"); } } - - @Command( identifier = "gui prestige", description = "GUI Prestige", aliases = {"prisonmanager prestige"} ) public void prisonManagerPrestige(CommandSender sender ) { - if ( isPrisonConfig("prestiges") ) { + if ( isPrisonConfig("prestiges") || isPrisonConfig( "prestige.enabled" ) ) { if (!(PrisonRanks.getInstance().getLadderManager().getLadder("prestiges").isPresent())) { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ranks ladder create prestiges"); @@ -137,7 +137,7 @@ private void prestigeByChat(CommandSender sender) { onlyPlayers = true ) private void prisonManagerPrestiges( CommandSender sender ) { - if ( !isPrisonConfig("prestiges") ) { + if ( !isPrisonConfig("prestiges") && !isPrisonConfig( "prestige.enabled" ) ) { sender.sendMessage(SpigotPrison.format(messages.getString("Message.PrestigesAreDisabled"))); return; } @@ -162,6 +162,4 @@ private void prisonManagerPrestiges( CommandSender sender ) { SpigotPlayerPrestigesGUI gui = new SpigotPlayerPrestigesGUI( player ); gui.open(); } - - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java index 9d5f3230b..d7c898a16 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java @@ -7,6 +7,9 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.spigot.gui.rank.SpigotPlayerRanksGUI; +/** + * @author RoyalBlueRanger + */ public class PrisonSpigotRanksCommands extends PrisonSpigotBaseCommands { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/sellall/SellAllPrisonCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/sellall/SellAllPrisonCommands.java new file mode 100644 index 000000000..bd62d9ba7 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/sellall/SellAllPrisonCommands.java @@ -0,0 +1,561 @@ +package tech.mcprison.prison.spigot.commands.sellall; + +import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Material; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.commands.Arg; +import tech.mcprison.prison.commands.Command; +import tech.mcprison.prison.integration.EconomyIntegration; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.modules.ModuleManager; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.commands.PrisonSpigotBaseCommands; +import tech.mcprison.prison.spigot.configs.SellAllConfig; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminGUI; +import tech.mcprison.prison.spigot.gui.sellall.SellAllPlayerGUI; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class SellAllPrisonCommands extends PrisonSpigotBaseCommands { + + private Configuration sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); + private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + private FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); + + public static boolean isEnabled(){ + return SpigotPrison.getInstance().getConfig().getString("sellall").equalsIgnoreCase("true"); + } + + @Command(identifier = "sellall", description = "SellAll main command", onlyPlayers = false) + private void sellAllCommands(CommandSender sender) { + + if (!isEnabled()) return; + + if (sender.hasPermission("prison.admin")) { + sender.dispatchCommand("sellall help"); + } else { + sender.dispatchCommand("sellall sell"); + } + } + + @Command(identifier = "sellall sell", description = "SellAll sell command", onlyPlayers = true) + private void SellAllSellCommand(CommandSender sender){ + + if (!isEnabled()) return; + + Player p = getSpigotPlayer(sender); + SellAllConfig sellAllConfigClass = new SellAllConfig(); + sellAllConfigClass.initialize(); + sellAllConfig = sellAllConfigClass.getFileSellAllConfig(); + + if (sellAllConfig.getString("Options.Sell_Permission_Enabled").equalsIgnoreCase("true")){ + if (!p.hasPermission("Options.Sell_Permission")){ + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Sell_Permission") + "]")); + } + } else if (!(sellAllConfig.getConfigurationSection("Items.") == null)){ + + // Get the Items config section + Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); + double moneyToGive = 0; + + // Get money to give + moneyToGive = getMoneyToGive(p, items, moneyToGive); + + // Get Spigot Player + SpigotPlayer sPlayer = new SpigotPlayer(p); + ModuleManager modMan = Prison.get().getModuleManager(); + Module module = modMan == null ? null : modMan.getModule( PrisonRanks.MODULE_NAME ).orElse( null ); + PrisonRanks rankPlugin = (PrisonRanks) module; + + // Get money to give + multiplier + moneyToGive = getMoneyWithMultiplier(moneyToGive, sPlayer, rankPlugin); + + // Get economy and add balance + EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); + economy.addBalance(sPlayer, moneyToGive); + + if (moneyToGive<0.001){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllNothingToSell"))); + } else { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllYouGotMoney") + moneyToGive)); + } + } else { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllEmpty"))); + } + } + + private double getMoneyWithMultiplier(double moneyToGive, SpigotPlayer sPlayer, PrisonRanks rankPlugin) { + if (sellAllConfig.getString("Options.Multiplier_Enabled").equalsIgnoreCase("true")) { + + double multiplier = Double.parseDouble(sellAllConfig.getString("Options.Multiplier_Default")); + + if (rankPlugin != null) { + if (rankPlugin.getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()).isPresent()) { + String playerRankName; + try { + playerRankName = rankPlugin.getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()).get().getRank("prestiges").name; + } catch (NullPointerException ex){ + playerRankName = null; + } + if (playerRankName != null) { + multiplier = Double.parseDouble(sellAllConfig.getString("Multiplier." + playerRankName + ".MULTIPLIER")); + } + } + } + List perms = sPlayer.getPermissions("prison.sellall.multiplier."); + double multiplierExtraByPerms = 0; + for (String multByPerm : perms){ + double multByPermDouble = Double.parseDouble(multByPerm.substring(26)); + if (!sellAllConfig.getString("Options.Multiplier_Permission_Only_Higher").equalsIgnoreCase("true")) { + multiplierExtraByPerms += multByPermDouble; + } else if (sellAllConfig.getString("Options.Multiplier_Permission_Only_Higher").equalsIgnoreCase("true") && multByPermDouble > multiplierExtraByPerms){ + multiplierExtraByPerms = multByPermDouble; + } + } + multiplier += multiplierExtraByPerms; + moneyToGive = moneyToGive * multiplier; + } + + return moneyToGive; + } + + private double getMoneyToGive(Player p, Set items, double moneyToGive) { + + // Get the player inventory + Inventory inv = p.getInventory(); + + // Get the items from the player inventory and for each of them check the conditions. + for (ItemStack itemStack : inv.getContents()){ + + if (itemStack != null) { + // Get the items strings from config and for each of them get the Material and value. + for (String key : items) { + String itemMaterial = sellAllConfig.getString("Items." + key + ".ITEM_ID"); + double value = Double.parseDouble(sellAllConfig.getString("Items." + key + ".ITEM_VALUE")); + int amount = 0; + + // Check if the item from the player inventory's on the config of items sellable + // So it gets the amount and then remove it from the inventory + if (itemMaterial != null && itemMaterial.equalsIgnoreCase(itemStack.getType().toString())) { + amount = itemStack.getAmount(); + p.getInventory().remove(itemStack); + } + // Get the new amount of money to give + if (amount != 0) { + moneyToGive = moneyToGive + (value * amount); + } + } + } + } + return moneyToGive; + } + + @Command(identifier = "sellall auto toggle", description = "Let the user enable or disable sellall auto", onlyPlayers = true) + private void sellAllAutoEnableUser(CommandSender sender){ + + if (!isEnabled()) return; + + Player p = getSpigotPlayer(sender); + SellAllConfig sellAllConfigClass = new SellAllConfig(); + sellAllConfigClass.initialize(); + sellAllConfig = sellAllConfigClass.getFileSellAllConfig(); + + if (!sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable").equalsIgnoreCase("true")){ + return; + } + + if (sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm").equalsIgnoreCase("true") && !p.hasPermission(sellAllConfig.getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission"))){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermissionToToggleAutoSell") + " [" + sellAllConfig.getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission") + "]")); + return; + } + + UUID playerUUID = p.getUniqueId(); + + if (sellAllConfig.getString("Users." + playerUUID + ".isEnabled") != null){ + if (sellAllConfig.getString("Users." + playerUUID + ".isEnabled").equalsIgnoreCase("true")){ + // Disable it + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Users." + playerUUID + ".isEnabled", false); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllAutoDisabled"))); + } else if (sellAllConfig.getString("Users." + playerUUID + ".isEnabled").equalsIgnoreCase("false")){ + // Enable it + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Users." + playerUUID + ".isEnabled", "true"); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); + } + } else { + // Enable it for the first time + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Users." + playerUUID + ".isEnabled", "true"); + conf.set("Users." + playerUUID + ".name", p.getName()); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); + } + } + + @Command(identifier = "sellall gui", description = "SellAll GUI command", onlyPlayers = true) + private void sellAllGuiCommand(CommandSender sender){ + + if (!isEnabled()) return; + + Player p = getSpigotPlayer(sender); + + if (p.isOp() || p.hasPermission("prison.admin")){ + SellAllAdminGUI gui = new SellAllAdminGUI(p); + gui.open(); + return; + } + + if (!sellAllConfig.getString("Options.GUI_Enabled").equalsIgnoreCase("true")){ + if (p.isOp() || p.hasPermission("prison.admin")) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllGUIDisabled"))); + return; + } + } + + if (sellAllConfig.getString("Options.GUI_Permission_Enabled").equalsIgnoreCase("true")){ + if (!p.hasPermission(sellAllConfig.getString("Options.GUI_Permission"))){ + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.GUI_Permission") + "]")); + } else if (sellAllConfig.getString("Options.Player_GUI_Enabled").equalsIgnoreCase("true")){ + if (sellAllConfig.getString("Options.Player_GUI_Permission_Enabled").equalsIgnoreCase("true")) { + if (!p.hasPermission(sellAllConfig.getString("Options.Player_GUI_Permission"))){ + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Player_GUI_Permission") + "]")); + return; + } + } + SellAllPlayerGUI gui = new SellAllPlayerGUI(p); + gui.open(); + } + } + } + + @Command(identifier = "sellall add", description = "SellAll add an item to the sellAll shop.", onlyPlayers = false) + private void sellAllAddCommand(CommandSender sender, + @Arg(name = "Item_ID", description = "The Item_ID or block to add to the sellAll Shop.") String itemID, + @Arg(name = "Value", description = "The value of the item.") Double value){ + + if (!isEnabled()) return; + if (sellAllConfig.getString("Options.Add_Permission_Enabled").equalsIgnoreCase("true")) { + if (!sender.hasPermission("Options.Add_Permission")) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Add_Permission") + "]")); + return; + } + } + if (itemID == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllPleaseAddItem"))); + return; + } + itemID = itemID.toUpperCase(); + + if (value == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllAddPrice"))); + return; + } + + try { + ItemStack blockAdd = XMaterial.valueOf(itemID).parseItem(); + if (blockAdd == null) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + return; + } + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Items." + itemID + ".ITEM_ID", blockAdd.getType().toString()); + conf.set("Items." + itemID + ".ITEM_VALUE", value); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + } catch (IllegalArgumentException ex){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + return; + } + + sender.sendMessage(SpigotPrison.format("&3[PRISON]&a ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); + } + + @Command(identifier = "sellall delete", description = "SellAll delete command, remove an item from shop.", onlyPlayers = false) + private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", description = "The Item_ID you want to remove.") String itemID){ + + if (!isEnabled()) return; + + if (sellAllConfig.getString("Options.Delete_Permission_Enabled").equalsIgnoreCase("true")) { + if (!sender.hasPermission("Options.Delete_Permission")) { + return; + } + } + if (itemID == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingID"))); + } + if (sellAllConfig.getConfigurationSection("Items." + itemID) == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllTagWarn") + itemID + messages.getString("Message.SellAllNotFoundStringConfig"))); + return; + } + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Items." + itemID + ".ITEM_ID", null); + conf.set("Items." + itemID + ".ITEM_VALUE", null); + conf.set("Items." + itemID, null); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllPrisonTag") + itemID + messages.getString("Message.SellAllDeletedSuccess"))); + } + + @Command(identifier = "sellall edit", description = "SellAll edit command, edit an item of Shop.", onlyPlayers = false) + private void sellAllEditCommand(CommandSender sender, + @Arg(name = "Item_ID", description = "The Item_ID or block to add to the sellAll Shop.") String itemID, + @Arg(name = "Value", description = "The value of the item.") Double value){ + + if (!isEnabled()) return; + + if (sellAllConfig.getString("Options.Add_Permission_Enabled").equalsIgnoreCase("true")) { + if (!sender.hasPermission("Options.Add_Permission")) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Add_Permission") + "]")); + return; + } + } + if (itemID == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllPleaseAddItem"))); + return; + } + itemID = itemID.toUpperCase(); + + if (value == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllAddPrice"))); + return; + } + + try { + ItemStack blockAdd = XMaterial.valueOf(itemID).parseItem(); + if (blockAdd == null) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + return; + } + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Items." + itemID + ".ITEM_ID", blockAdd.getType().toString()); + conf.set("Items." + itemID + ".ITEM_VALUE", value); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + e.printStackTrace(); + } + } catch (IllegalArgumentException ex){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + return; + } + + + sender.sendMessage(SpigotPrison.format("&3[PRISON]&a ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllCommandEditSuccess"))); + } + + @Command(identifier = "sellall multiplier", description = "SellAll multiplier command list", onlyPlayers = false) + private void sellAllMultiplierCommand(CommandSender sender){ + + if (!isEnabled()) return; + + if (sellAllConfig.getString("Options.Multiplier_Command_Permission_Enabled").equalsIgnoreCase("true")){ + if (!(sender.hasPermission(sellAllConfig.getString("Options.Multiplier_Command_Permission")))){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Multiplier_Command_Permission") + "]")); + return; + } + } + if (!(sellAllConfig.getString("Options.Multiplier_Enabled").equalsIgnoreCase("true"))){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + return; + } + + sender.dispatchCommand("sellall multiplier help"); + } + + @Command(identifier = "sellall multiplier add", description = "SellAll add a multiplier.", onlyPlayers = false) + private void sellAllAddMultiplierCommand(CommandSender sender, + @Arg(name = "Prestige", description = "Prestige to hook to the multiplier.") String prestige, + @Arg(name = "multiplier", description = "Multiplier value.") Double multiplier){ + + if (!isEnabled()) return; + if (addMultiplierConditions(sender, prestige, multiplier)) return; + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Multiplier." + prestige + ".PRESTIGE_NAME", prestige); + conf.set("Multiplier." + prestige + ".MULTIPLIER", multiplier); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + return; + } + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultiplierEditSaveSuccess"))); + } + + private boolean addMultiplierConditions(CommandSender sender, String prestige, Double multiplier) { + + if (sellAllConfig.getString("Options.Multiplier_Command_Permission_Enabled").equalsIgnoreCase("true")){ + if (!(sender.hasPermission(sellAllConfig.getString("Options.Multiplier_Command_Permission")))){ + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + sellAllConfig.getString("Options.Multiplier_Command_Permission") + "]")); + return true; + } + } + if (!(sellAllConfig.getString("Options.Multiplier_Enabled").equalsIgnoreCase("true"))){ + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + return true; + } + if (prestige == null){ + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultiplierWrongFormat"))); + return true; + } + if (multiplier == null){ + + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultiplierWrongFormat"))); + return true; + } + + PrisonRanks rankPlugin = (PrisonRanks) (Prison.get().getModuleManager() == null ? null : Prison.get().getModuleManager().getModule(PrisonRanks.MODULE_NAME).orElse(null)); + if (rankPlugin == null) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllRanksDisabled"))); + return true; + } + + boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").isPresent(); + if (!isPrestigeLadder) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllPrestigeLadderNotFound"))); + return true; + } + + boolean isARank = rankPlugin.getRankManager().getRank(prestige) != null; + if (!isARank) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllCantFindPrestigeOrRank") + prestige)); + return true; + } + + boolean isInPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").get().containsRank(rankPlugin.getRankManager().getRank(prestige).id); + if (!isInPrestigeLadder) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllRankNotFoundInPrestigeLadder") + prestige)); + return true; + } + return false; + } + + @Command(identifier = "sellall multiplier delete", description = "SellAll delete a multiplier.", onlyPlayers = false) + private void sellAllDeleteMultiplierCommand(CommandSender sender, + @Arg(name = "Prestige", description = "Prestige hooked to the multiplier.") String prestige){ + + if (!isEnabled()) return; + + if (prestige == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultiplierFormat"))); + return; + } + if (sellAllConfig.getConfigurationSection("Multiplier." + prestige) == null){ + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllCantFindMultiplier") + prestige + messages.getString("Message.SellAllCantFindMultiplier2"))); + return; + } + + try { + sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Multiplier." + prestige, null); + conf.save(sellAllFile); + } catch (IOException e) { + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); + return; + } + sender.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllMultiplierDeleteSuccess"))); + } + + @Command(identifier = "sellall setdefault", description = "SellAll default values ready to go.", onlyPlayers = false) + private void sellAllSetDefaultCommand(CommandSender sender){ + + if (!isEnabled()) return; + + if (sender.hasPermission("prison.admin")){ + valueSaver("COBBLESTONE", 50, sender); + valueSaver("STONE", 50, sender); + valueSaver("COAL",50, sender); + valueSaver("COAL_BLOCK", 450, sender); + valueSaver("IRON_INGOT",75, sender); + valueSaver("IRON_BLOCK",600, sender); + valueSaver("REDSTONE", 101, sender); + valueSaver("REDSTONE_BLOCK", 909, sender); + valueSaver("GOLD_INGOT", 122, sender); + valueSaver("GOLD_BLOCK", 1100, sender); + valueSaver("DIAMOND", 200, sender); + valueSaver("DIAMOND_BLOCK", 1800, sender); + valueSaver("EMERALD", 300, sender); + valueSaver("EMERALD_BLOCK", 2700, sender); + valueSaver("LAPIS_LAZULI", 70, sender); + valueSaver("LAPIS_BLOCK", 630, sender); + + sender.sendMessage(SpigotPrison.format("&7[&3Prison&7] &aDefault Values added with success!")); + } else { + sender.sendMessage(SpigotPrison.format("&7[&3Prison Error&7] &cSorry but you're missing the permission [prison.admin]!")); + } + } + + private void valueSaver(String material, int value, CommandSender sender){ + Material materialM = Material.matchMaterial(material); + if (materialM == null){ + return; + } else { + material = materialM.name(); + } + sender.dispatchCommand( "sellall add " + material + " " + value); + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java index 742bdf69b..40a54a776 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java @@ -23,6 +23,8 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.spigot.block.SpigotItemStack; + /** * Different Spigot versions have different methods. * The compatibility system ensures that each version can be used with the same code. @@ -39,6 +41,10 @@ public interface Compatibility public ItemStack getItemInMainHand(Player player); + public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e); + + public SpigotItemStack getPrisonItemInMainHand(Player player); + public void breakItemInMainHand(Player player); public void playIronDoorSound(Location loc); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java index 56a07c417..03aabad68 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; public interface CompatibilityBlocks { @@ -31,11 +32,17 @@ public interface CompatibilityBlocks { public BlockTestStats testCountAllBlockTypes(); - public int getDurabilityMax( ItemStack itemInHand ); + public int getDurabilityMax( SpigotItemStack itemInHand ); - public int getDurability( ItemStack itemInHand ); - - public void setDurability( ItemStack itemInHand, int newDurability ); + public boolean hasDurability( SpigotItemStack itemStack ); + + public int getDurability( SpigotItemStack itemInHand ); + + public boolean setDurability( SpigotItemStack itemInHand, int newDurability ); + +// public int getDurability( SpigotItemStack itemInHand ); +// +// public void setDurability( SpigotItemStack itemInHand, int newDurability ); public void setBlockFace( Block bBlock, BlockFace blockFace ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java index 924d24955..fc10cebc5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java @@ -29,13 +29,29 @@ public class CompatibilityCache { private Map xMaterialCache; + public CompatibilityCache() { super(); this.blockTypeCache = new TreeMap<>(); this.xMaterialCache = new TreeMap<>(); + + initializeForcedCache(); } + /** + * If a block is not being mapped to a specific type, then it can be + * forced by assigning it here at server startup. This should only be used + * as a last ditch effort to assign the correct block types. + * + */ + private void initializeForcedCache() { + + xMaterialCache.put( "STATIONARY_WATER", XMaterial.WATER ); + xMaterialCache.put( "WATER", XMaterial.WATER ); + + } + public BlockType getCachedBlockType( Block spigotBlock, byte data ) { String key = spigotBlock.getType().name() + ( data <= 0 ? "" : ":" +data); @@ -82,7 +98,7 @@ public XMaterial getCachedXMaterial( PrisonBlock prisonBlock ) XMaterial xMat = xMaterialCache.get( key ); // Using VOID_AIR as temp placeholder for null values: - return xMat; // xMat == XMaterial.VOID_AIR ? null : xMat; + return xMat; // xMat == NULL_TOKEN ? null : xMat; } public void putCachedXMaterial( PrisonBlock prisonBlock, XMaterial xMat ) @@ -90,8 +106,8 @@ public void putCachedXMaterial( PrisonBlock prisonBlock, XMaterial xMat ) String key = prisonBlock.getBlockName(); if ( !xMaterialCache.containsKey( key ) ) { - // Using VOID_AIR as temp placeholder for null values: - xMaterialCache.put( key, xMat == null ? XMaterial.VOID_AIR : xMat ); + // Using NULL_TOKEN as temp placeholder for null values: + xMaterialCache.put( key, xMat == null ? NULL_TOKEN : xMat ); } } @@ -100,15 +116,15 @@ public XMaterial getCachedXMaterial( Block spigotBlock, byte data ) { XMaterial xMat = xMaterialCache.get( key ); - // Using VOID_AIR as temp placeholder for null values: - return xMat; // xMat == XMaterial.VOID_AIR ? null : xMat; + // Do not use NULL_TOKEN since this must return null if it does not exist: + return xMat; } public void putCachedXMaterial( Block spigotBlock, byte data, XMaterial xMat ) { String key = spigotBlock.getType().name() + ( data <= 0 ? "" : ":" +data); if ( !xMaterialCache.containsKey( key ) ) { // Using VOID_AIR as temp placeholder for null values: - xMaterialCache.put( key, xMat == null ? XMaterial.VOID_AIR : xMat ); + xMaterialCache.put( key, xMat == null ? NULL_TOKEN : xMat ); } } @@ -125,7 +141,7 @@ public void putCachedXMaterial( BlockType blockType, byte data, XMaterial xMat ) if ( !xMaterialCache.containsKey( key ) ) { // Using VOID_AIR as temp placeholder for null values: - xMaterialCache.put( key, xMat == null ? XMaterial.VOID_AIR : xMat ); + xMaterialCache.put( key, xMat == null ? NULL_TOKEN : xMat ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java index d1372fa18..34981a7df 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java @@ -7,6 +7,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.block.SpigotItemStack; + public class Spigot113 extends Spigot113GUI implements Compatibility { @@ -30,6 +33,16 @@ public ItemStack getItemInMainHand(Player player) { return player.getInventory().getItemInMainHand(); } + + public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + } + + public SpigotItemStack getPrisonItemInMainHand(Player player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + } + + @Override public void playIronDoorSound(Location loc) { loc.getWorld().playEffect(loc, Effect.IRON_DOOR_TOGGLE, null); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index f01632ae0..b82418a98 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -6,12 +6,15 @@ import org.bukkit.block.data.Directional; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes.InternalBlockTypes; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; public abstract class Spigot113Blocks @@ -49,6 +52,8 @@ public PrisonBlock getPrisonBlock(Block spigotBlock) { if ( xMat != null ) { pBlock = new PrisonBlock( xMat.name() ); } + // ignore nulls because errors were logged in getXMaterial() so they only + // are logged once return pBlock; } @@ -69,35 +74,46 @@ public BlockType getBlockType(ItemStack spigotStack) { } public XMaterial getXMaterial( Block spigotBlock ) { - XMaterial results = getCachedXMaterial( spigotBlock, NO_DATA_VALUE ); - - if ( results == null ) { - if ( spigotBlock != null ) { - results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); + XMaterial results = NULL_TOKEN; + + if ( spigotBlock != null ) { + results = getCachedXMaterial( spigotBlock, NO_DATA_VALUE ); + + if ( results == null ) { + results = XMaterial.matchXMaterial( spigotBlock.getType() ); putCachedXMaterial( spigotBlock, NO_DATA_VALUE, results ); + + if ( results == null ) { + Output.get().logWarn( "Spigot113Blocks.getXMaterial() : " + + "Spigot block cannot be mapped to a XMaterial : " + + spigotBlock.getType().name() + + " SpigotBlock = " + ( spigotBlock == null ? "null" : + spigotBlock.getType().name())); + } + } } + return results == NULL_TOKEN ? null : results; } public XMaterial getXMaterial( PrisonBlock prisonBlock ) { - XMaterial results = null; + XMaterial results = NULL_TOKEN; if ( prisonBlock != null ) { results = getCachedXMaterial( prisonBlock ); if ( results == null ) { - String blockName = prisonBlock.getBlockName(); + String blockName = prisonBlock.getBlockName(); - results = XMaterial.matchXMaterial( blockName ).orElse( null ); + results = XMaterial.matchXMaterial( blockName ).orElse( null ); putCachedXMaterial( prisonBlock, results ); } - } return results == NULL_TOKEN ? null : results; @@ -226,22 +242,65 @@ else if ( mat.isItem() ) { } - public int getDurabilityMax( ItemStack itemInHand ) { - return itemInHand.getType().getMaxDurability(); + public int getDurabilityMax( SpigotItemStack itemInHand ) { + return itemInHand.getBukkitStack().getType().getMaxDurability(); } - public int getDurability( ItemStack itemInHand ) { + + @Override + public boolean hasDurability( SpigotItemStack itemInHand ) + { + boolean results = false; - Damageable damage = (Damageable) itemInHand.getItemMeta(); - return damage.getDamage(); + if ( itemInHand != null && itemInHand.getBukkitStack().hasItemMeta() && + itemInHand.getBukkitStack().getItemMeta() instanceof Damageable ) { + + Damageable item = (Damageable) itemInHand.getBukkitStack().getItemMeta(); + results = item.hasDamage(); + } + + return results; } - - public void setDurability( ItemStack itemInHand, int newDamage ) { + + @Override + public int getDurability( SpigotItemStack itemInHand ) + { + int results = 0; + + if ( itemInHand != null && itemInHand.getBukkitStack().hasItemMeta() && + itemInHand.getBukkitStack().getItemMeta() instanceof Damageable ) { + Damageable item = (Damageable) itemInHand.getBukkitStack().getItemMeta(); + results = item.getDamage(); + } - Damageable damage = (Damageable) itemInHand.getItemMeta(); - damage.setDamage( newDamage ); + return results; + } + + @Override + public boolean setDurability( SpigotItemStack itemInHand, int newDamage ) { + boolean results = false; + if ( itemInHand != null && itemInHand.getBukkitStack().getItemMeta() != null && + itemInHand.getBukkitStack().getItemMeta() instanceof Damageable ) { + Damageable item = (Damageable) itemInHand.getBukkitStack().getItemMeta(); + + item.setDamage( newDamage ); + results = itemInHand.getBukkitStack().setItemMeta((ItemMeta) item); + } + return results; } +// public int getDurability( SpigotItemStack itemInHand ) { +// +// Damageable damage = (Damageable) itemInHand.getBukkitStack().getItemMeta(); +// return damage.getDamage(); +// } +// +// public void setDurability( SpigotItemStack itemInHand, int newDamage ) { +// +// Damageable damage = (Damageable) itemInHand.getBukkitStack().getItemMeta(); +// damage.setDamage( newDamage ); +// } + /** * This is called setBlockFace, but it is really intended for use with ladders. * The block face is the face in which to place the ladder. So when diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java index 1fcae90ce..92c1eff92 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java @@ -25,6 +25,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.block.SpigotItemStack; + /** * @author Faizaan A. Datoo */ @@ -51,6 +54,16 @@ public ItemStack getItemInMainHand(Player player ) { return player.getItemInHand(); } + + public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + } + + public SpigotItemStack getPrisonItemInMainHand(Player player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + } + + @Override public void playIronDoorSound(Location loc) { loc.getWorld().playEffect(loc, Effect.DOOR_TOGGLE, null); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java index f2cf461b5..00e776b00 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java @@ -10,6 +10,8 @@ import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; public abstract class Spigot18Blocks @@ -36,7 +38,7 @@ public abstract class Spigot18Blocks */ @SuppressWarnings( "deprecation" ) public BlockType getBlockType(Block spigotBlock) { - BlockType results = null; + BlockType results = BlockType.NULL_BLOCK; if ( spigotBlock != null ) { @@ -59,7 +61,7 @@ public BlockType getBlockType(Block spigotBlock) { if ( results == null ) { - Output.get().logWarn( "Spigot1.8Blocks.getBlockType() : " + + Output.get().logWarn( "Spigot18Blocks.getBlockType() : " + "Spigot block cannot be mapped to a prison BlockType : " + spigotBlock.getType().name() + " id = " + id + " data = " + data + @@ -82,8 +84,11 @@ public PrisonBlock getPrisonBlock(Block spigotBlock) { XMaterial xMat = getXMaterial( spigotBlock ); if ( xMat != null ) { - pBlock = new PrisonBlock( xMat.name() ); + pBlock = SpigotPrison.getInstance().getPrisonBlockTypes().getBlockTypesByName( xMat.name() ); +// pBlock = new PrisonBlock( xMat.name() ); } + // ignore nulls because errors were logged in getXMaterial() so they only + // are logged once return pBlock; } @@ -91,7 +96,7 @@ public PrisonBlock getPrisonBlock(Block spigotBlock) { @SuppressWarnings( "deprecation" ) public BlockType getBlockType( ItemStack spigotStack ) { - BlockType results = null; + BlockType results = BlockType.NULL_BLOCK; if ( spigotStack != null ) { @@ -111,43 +116,67 @@ public BlockType getBlockType( ItemStack spigotStack ) { @SuppressWarnings( "deprecation" ) public XMaterial getXMaterial( Block spigotBlock ) { - XMaterial results = null; + XMaterial results = NULL_TOKEN; if ( spigotBlock != null ) { -// int id = spigotBlock.getType().getId(); - short data = spigotBlock.getData(); + byte data = spigotBlock.getData(); - results = getCachedXMaterial( spigotBlock, (byte) data ); + results = getCachedXMaterial( spigotBlock, data ); if ( results == null ) { - - String blockName = spigotBlock.getType().name() + - ( data > 0 ? ":" + data : "" ); - results = XMaterial.matchXMaterial( blockName ).orElse( null ); + String blockName = spigotBlock.getType().name() + ":" + data; + results = XMaterial.matchXMaterial( blockName ).orElse( null ); + +// if ( results == null ) { +// +// Output.get().logInfo( "#### Spigot18Blocks.getXMaterial(Block) : %s => %s ", +// blockName, (results == null ? "null" : results.name() )); +// } + + + if ( results == null ) { + // Last chance: try to match by id: + int id = spigotBlock.getType().getId(); + results = XMaterial.matchXMaterial( id, data ).orElse( null ); + } - putCachedXMaterial( spigotBlock, (byte) data, results ); + if ( results == null ) { + // Last chance, try to match without data. If it matches, then + // the cache will be setup with a data appended so as to bypass all this + // extra checks: + results = getCachedXMaterial( spigotBlock, (byte) 0 ); + } + + putCachedXMaterial( spigotBlock, data, results ); + + if ( results == null ) { + Output.get().logWarn( "Spigot18Blocks.getXMaterial() : " + + "Spigot block cannot be mapped to a XMaterial : " + + spigotBlock.getType().name() + + " SpigotBlock = " + ( spigotBlock == null ? "null" : + spigotBlock.getType().name()) + + " data = " + data ); + } } - } return results == NULL_TOKEN ? null : results; } public XMaterial getXMaterial( PrisonBlock prisonBlock ) { - XMaterial results = null; + XMaterial results = NULL_TOKEN; if ( prisonBlock != null ) { results = getCachedXMaterial( prisonBlock ); if ( results == null ) { - String blockName = prisonBlock.getBlockName(); + String blockName = prisonBlock.getBlockName(); - results = XMaterial.matchXMaterial( blockName ).orElse( null ); + results = XMaterial.matchXMaterial( blockName ).orElse( null ); putCachedXMaterial( prisonBlock, results ); } - } return results == NULL_TOKEN ? null : results; @@ -156,7 +185,7 @@ public XMaterial getXMaterial( PrisonBlock prisonBlock ) { public XMaterial getXMaterial( BlockType blockType ) { - XMaterial results = null; + XMaterial results = NULL_TOKEN; if ( blockType != null && blockType != BlockType.IGNORE ) { short data = blockType.getData(); @@ -351,20 +380,55 @@ public BlockTestStats testCountAllBlockTypes() { - public int getDurabilityMax( ItemStack itemInHand ) { - return itemInHand.getType().getMaxDurability(); + public int getDurabilityMax( SpigotItemStack itemInHand ) { + return itemInHand.getBukkitStack().getType().getMaxDurability(); } @SuppressWarnings( "deprecation" ) - public int getDurability( ItemStack itemInHand ) { - return itemInHand.getDurability(); + @Override + public boolean hasDurability( SpigotItemStack itemStack ) { + boolean results = false; + + if ( itemStack != null ) { + results = itemStack.getBukkitStack().getDurability() > 0; + } + + return results; } - + + @SuppressWarnings( "deprecation" ) + @Override + public int getDurability( SpigotItemStack itemStack ) { + int results = 0; + + if ( itemStack != null ) { + results = itemStack.getBukkitStack().getDurability(); + } + + return results; + } + @SuppressWarnings( "deprecation" ) - public void setDurability( ItemStack itemInHand, int newDurability ) { - itemInHand.setDurability( (short) newDurability ); + @Override + public boolean setDurability( SpigotItemStack itemStack, int damage ) { + boolean results = false; + if ( itemStack != null ) { + itemStack.getBukkitStack().setDurability( (short) damage ); + results = true; + } + return results; } +// @SuppressWarnings( "deprecation" ) +// public int getDurability( SpigotItemStack itemInHand ) { +// return itemInHand.getBukkitStack().getDurability(); +// } +// +// @SuppressWarnings( "deprecation" ) +// public void setDurability( SpigotItemStack itemInHand, int newDurability ) { +// itemInHand.getBukkitStack().setDurability( (short) newDurability ); +// } + public void setBlockFace( Block spigotBlock, BlockFace blockFace ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java index 707d3359e..f0f4025d1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java @@ -25,6 +25,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.block.SpigotItemStack; + /** * Spigot 1.9, 1.10, and 1.11. * @@ -53,6 +56,16 @@ public ItemStack getItemInMainHand(Player player) { return player.getInventory().getItemInMainHand(); } + + public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + } + + public SpigotItemStack getPrisonItemInMainHand(Player player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + } + + @Override public void playIronDoorSound(Location loc) { loc.getWorld().playEffect(loc, Effect.IRON_DOOR_TOGGLE, null); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/GuiConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/GuiConfig.java index d8b0cc776..b25b2ab17 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/GuiConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/GuiConfig.java @@ -21,34 +21,32 @@ public class GuiConfig extends SpigotConfigComponents{ // Check if the GuiConfig's enabled public GuiConfig() { - if (Objects.requireNonNull(SpigotPrison.getInstance().getConfig().getString("prison-gui-enabled")).equalsIgnoreCase("true")){ - initialize(); - } + // Will make ALWAYS the config even if GUIs are disabled + initialize(); } public void initialize() { // Filepath File file = new File(SpigotPrison.getInstance().getDataFolder() + "/GuiConfig.yml"); - fileMaker(file); - conf = YamlConfiguration.loadConfiguration(file); - // Everything's here (not anymore...) + // Values to write down into the config values(); + // Count and save if (changeCount > 0) { try { conf.save(file); - Output.get().logInfo("&aThere were &b%d &anew values added to the GuiConfig.yml file located at &b%s", - changeCount, file.getAbsoluteFile()); + Output.get().logInfo("&aThere were &b%d &anew values added to the GuiConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile()); } catch (IOException e) { - Output.get().logInfo("&4Failed to save &b%d &4new values to the GuiConfig.yml file located at " + - "&b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage()); + Output.get().logInfo("&4Failed to save &b%d &4new values to the GuiConfig.yml file located at " + "&b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage()); } } + + conf = YamlConfiguration.loadConfiguration(file); } private void dataConfig(String key, String value){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java index 8ca5b365b..06948b328 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java @@ -26,7 +26,7 @@ public MessagesConfig() { public void initialize() { // Filepath - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/configs/" + SpigotPrison.getInstance().getConfig().getString("default-language") + ".yml"); + File file = new File(SpigotPrison.getInstance().getDataFolder() + "/module_conf/lang/" + SpigotPrison.getInstance().getConfig().getString("default-language") + ".yml"); // Check if the config exists fileMaker(file); @@ -40,12 +40,14 @@ public void initialize() { if (changeCount > 0) { try { conf.save(file); - Output.get().logInfo( "&aThere were &b%d &anew values added for the language files " + "used by the GuiConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile() ); + Output.get().logInfo("&aThere were &b%d &anew values added for the language files " + "used by the GuiConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile()); } catch (IOException e) { - Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + "used by the GuiConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage() ); + Output.get().logInfo("&4Failed to save &b%d &4new values for the language files " + "used by the GuiConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage()); } } + + conf = YamlConfiguration.loadConfiguration(file); } private void dataConfig(String key, String value){ @@ -154,56 +156,96 @@ private void values(){ dataConfig("Lore.noRanksFoundSetup6", "&1/ranks autoConfigure full !"); dataConfig("Lore.noRanksFoundSetup7", "&3Please replace the X with the starting price and"); dataConfig("Lore.noRanksFoundSetup8", "&3multiplier, default price = 50000, multiplier = 1.5."); - dataConfig("Message.CantGetRanksAdmin", "&3[PRISON WARN] &cCan't get Ranks, there might be no ranks or the Ranks module's disabled."); - dataConfig("Message.CantRunGUIFromConsole", "&7[&3Info&7] You cannot run the GUI from the console."); - dataConfig("Message.DefaultLadderEmpty", "&7[&cError&7] &cThe default ladder has no rank."); - dataConfig("Message.NoSellAllItems", "&cSorry but there aren't SellAll Items to show."); - dataConfig("Message.EmptyGui","&cSorry, the GUI looks empty."); - dataConfig("Message.NoBlocksMine","&cSorry but there aren't blocks inside this Mine."); - dataConfig("Message.NoMines", "&cSorry but there aren't Mines to show."); - dataConfig("Message.NoRankupCommands", "&cSorry, but there aren't rankUpCommands for this ranks, please create one to use this GUI!"); - dataConfig("Message.NoLadders", "&cSorry but there aren't ladders to show."); + dataConfig("Message.CantGetRanksAdmin", "&7[&3PRISON WARN&7] &cCan't get Ranks, there might be no ranks or the Ranks module's disabled."); + dataConfig("Message.CantRunGUIFromConsole", "&7[&3PRISON INFO&7] You cannot run the GUI from the console."); + dataConfig("Message.DefaultLadderEmpty", "&7[&3PRISON ERROR&7] &cThe default ladder has no rank."); + dataConfig("Message.NoSellAllItems", "&7[&3PRISON WARN&7] &cSorry but there aren't SellAll Items to show."); + dataConfig("Message.EmptyGui","&7[&3PRISON WARN&7] &cSorry, the GUI looks empty."); + dataConfig("Message.NoBlocksMine","&7[&3PRISON WARN&7] &cSorry but there aren't blocks inside this Mine."); + dataConfig("Message.NoMines", "&7[&3PRISON WARN&7] &cSorry but there aren't Mines to show."); + dataConfig("Message.NoRankupCommands", "&7[&3PRISON WARN&7] &cSorry, but there aren't rankUpCommands for this ranks, please create one to use this GUI!"); + dataConfig("Message.NoLadders", "&7[&3PRISON WARN&7] &cSorry but there aren't ladders to show."); dataConfig("Message.NoRanksPrestigesLadder", "&3[PRISON WARN] &cThere aren't ranks in the -prestiges- ladder!"); - dataConfig("Message.NoRanksFoundAdmin", "&cSorry, but before using this GUI you should create a Rank in this ladder!"); - dataConfig("Message.NoRanksFound", "&cSorry, but there aren't Ranks in the default or selected ladder!"); - dataConfig("Message.NoRanksFoundHelp1", "&cSorry, but there aren't Ranks in the default or selected ladder or the ladder &3["); + dataConfig("Message.NoRanksFoundAdmin", "&7[&3PRISON WARN&7] &cSorry, but before using this GUI you should create a Rank in this ladder!"); + dataConfig("Message.NoRanksFound", "&7[&3PRISON WARN&7] &cSorry, but there aren't Ranks in the default or selected ladder!"); + dataConfig("Message.NoRanksFoundHelp1", "&7[&3PRISON WARN&7] &cSorry, but there aren't Ranks in the default or selected ladder or the ladder &3["); dataConfig("Message.NoRanksFoundHelp2", "]&c isn't found!"); - dataConfig("Message.LadderPrestigesNotFound", "&3[PRISON WARN] &cLadder -prestiges- not found!"); - dataConfig("Message.TooManyBlocks","&cSorry, but there're too many Blocks and the max's 54 for the GUI"); - dataConfig("Message.TooManyLadders","&cSorry, but there're too many ladders and the max's 54 for the GUI"); - dataConfig("Message.TooManyMines","&cSorry, but there're too many mines and the max's 54 for the GUI"); - dataConfig("Message.TooManyRankupCommands","&cSorry, but there're too many RankupCommands and the max's 54 for the GUI"); - dataConfig("Message.TooManyRanks", "&cSorry, but there're too many ranks and the max's 54 for the GUI"); - dataConfig("Message.TooManySellAllItems", "&3[PRISON WARN] &cThere are too many items and the MAX for the GUI's 54!"); + dataConfig("Message.LadderPrestigesNotFound", "&7[&3PRISON WARN&7] &cLadder -prestiges- not found!"); + dataConfig("Message.TooManyBlocks","&7[&3PRISON WARN&7] &cSorry, but there're too many Blocks and the max's 54 for the GUI"); + dataConfig("Message.TooManyLadders","&7[&3PRISON WARN&7] &cSorry, but there're too many ladders and the max's 54 for the GUI"); + dataConfig("Message.TooManyMines","&7[&3PRISON WARN&7] &cSorry, but there're too many mines and the max's 54 for the GUI"); + dataConfig("Message.TooManyRankupCommands","&7[&3PRISON WARN&7] &cSorry, but there're too many RankupCommands and the max's 54 for the GUI"); + dataConfig("Message.TooManyRanks", "&7[&3PRISON WARN&7] &cSorry, but there're too many ranks and the max's 54 for the GUI"); + dataConfig("Message.TooManySellAllItems", "&7[&3PRISON WARN&7] &cThere are too many items and the MAX for the GUI's 54!"); dataConfig("Message.ZeroBlocksReset1","&8Set a mine's delay "); dataConfig("Message.ZeroBlocksReset2","&8before reset when it "); dataConfig("Message.ZeroBlocksReset3","&8reaches zero blocks."); - dataConfig("Message.mineNameRename", "&7[&3Info&7] &3Please write the &6mineName &3you'd like to use and &6submit&3."); - dataConfig("Message.mineNameRenameClose", "&7[&3Info&7] &3Input &cclose &3to cancel or wait &c30 seconds&3."); - dataConfig("Message.mineNameRenameClosed", "&7[&3Info&7] &cRename mine closed, nothing got changed!"); - dataConfig("Message.mineOrGuiDisabled", "&7[&3Info&7] &cGUI and/or GUI Mines is not enabled. Check GuiConfig.yml."); - dataConfig("Message.mineMissingGuiPermission", "&7[&3Info&7] &cYou lack the permissions to use GUI mines"); - dataConfig("Message.OutOfTimeNoChanges", "&cYou ran out of time, nothing changed."); - dataConfig("Message.PrestigeCancelled", "&7[&3Info&7] &cPrestige cancelled!"); - dataConfig("Message.PrestigeCancelledWrongKeyword", "&7[&3Info&7] &cPrestige cancelled, you didn't type the word: confirm"); - dataConfig("Message.PrestigeRanOutOfTime", "&7[&3Info&7] &cYou ran out of time, prestige cancelled."); - dataConfig("Message.PrestigesDisabledDefault", "&7[&3Info&7] &cPrestiges are disabled by default, please edit it in your config.yml!"); - dataConfig("Message.ConfirmPrestige", "&7[&3Info&7] &aConfirm&3: Type the word &aconfirm &3 to confirm"); - dataConfig("Message.CancelPrestige", "&7[&3Info&7] &cCancel&3: Type the word &ccancel &3to cancel, &cyou've 30 seconds."); - dataConfig("Message.PrestigesAreDisabled", "&7[&3Info&7] &cPrestiges are disabled. Check config.yml."); - dataConfig("Message.GuiOrPrestigesDisabled", "&7[&3Info&7] &cGUI and/or GUI Prestiges is not enabled. Check GuiConfig.yml."); - dataConfig("Message.CantFindPrestiges", "&7[&cError&7] &cThe prestige ladder has no prestiges!"); - dataConfig("Message.missingGuiPrestigesPermission", "&7[&3Info&7] &cYou lack the permissions to use GUI prestiges"); - dataConfig("Message.rankTagRename", "&7[&3Info&7] &3Please write the &6tag &3you'd like to use and &6submit&3."); - dataConfig("Message.rankTagRenameClose", "&7[&3Info&7] &3Input &cclose &3to cancel or wait &c30 seconds&3."); - dataConfig("Message.rankTagRenameClosed", "&7[&3Info&7] &cRename tag closed, nothing got changed!"); - dataConfig("Message.rankGuiDisabledOrAllGuiDisabled", "&7[&3Info&7] &cGUI and/or GUI ranks is not enabled. Check GuiConfig.yml (%s %s)"); - dataConfig("Message.rankGuiMissingPermission", "&7[&3Info&7] &cYou lack the permissions to use GUI ranks"); - dataConfig("Setup.Message.MissingPermission", "&7[&cError&7] &cSorry but you don't have the permission [-prison.setup- or -prison.admin-]!"); - dataConfig("Setup.Message.WrongFormat", "&7[&cError&7] &cYou're missing the last argument -mines- or -ranks-, / setup -mines- or -ranks- !"); - dataConfig("Setup.Message.WelcomeToRanksSetup", "&7[&3Info&7] &3Hi and welcome to the ranks setup, please wait until it'll be completed!"); - dataConfig("Setup.Message.SuccessRanksSetup", "&7[&3Info&7] &3The ranks setup got completed with &asuccess&3 and the ranks got added to the default ladder,\n please check the logs if something's missing!"); - dataConfig("Setup.Message.Aborted", "&7[&3Info&7] &3Prison Setup Cancelled."); + dataConfig("Message.mineNameRename", "&7[&3PRISON INFO&7] &3Please write the &6mineName &3you'd like to use and &6submit&3."); + dataConfig("Message.mineNameRenameClose", "&7[&3PRISON INFO&7] &3Input &cclose &3to cancel or wait &c30 seconds&3."); + dataConfig("Message.mineNameRenameClosed", "&7[&3PRISON INFO&7] &cRename mine closed, nothing got changed!"); + dataConfig("Message.mineOrGuiDisabled", "&7[&3PRISON INFO&7] &cGUI and/or GUI Mines is not enabled. Check GuiConfig.yml."); + dataConfig("Message.mineMissingGuiPermission", "&7[&3PRISON INFO&7] &cYou lack the permissions to use GUI mines"); + dataConfig("Message.OutOfTimeNoChanges", "&7[&3PRISON&7] &cYou ran out of time, nothing changed."); + dataConfig("Message.PrestigeCancelled", "&7[&3PRISON INFO&7] &cPrestige cancelled!"); + dataConfig("Message.PrestigeCancelledWrongKeyword", "&7[&3PRISON INFO&7] &cPrestige cancelled, you didn't type the word: confirm"); + dataConfig("Message.PrestigeRanOutOfTime", "&7[&3PRISON INFO&7] &cYou ran out of time, prestige cancelled."); + dataConfig("Message.PrestigesDisabledDefault", "&7[&3PRISON INFO&7] &cPrestiges are disabled by default, please edit it in your config.yml!"); + dataConfig("Message.ConfirmPrestige", "&7[&3PRISON INFO&7] &aConfirm&3: Type the word &aconfirm &3 to confirm"); + dataConfig("Message.CancelPrestige", "&7[&3PRISON INFO&7] &cCancel&3: Type the word &ccancel &3to cancel, &cyou've 30 seconds."); + dataConfig("Message.PrestigesAreDisabled", "&7[&3PRISON INFO&7] &cPrestiges are disabled. Check config.yml."); + dataConfig("Message.GuiOrPrestigesDisabled", "&7[&3PRISON INFO&7] &cGUI and/or GUI Prestiges is not enabled. Check GuiConfig.yml."); + dataConfig("Message.CantFindPrestiges", "&7[&3PRISON ERROR&7] &cThe prestige ladder has no prestiges!"); + dataConfig("Message.missingGuiPrestigesPermission", "&7[&3PRISON INFO&7] &cYou lack the permissions to use GUI prestiges"); + dataConfig("Message.rankTagRename", "&7[&3PRISON INFO&7] &3Please write the &6tag &3you'd like to use and &6submit&3."); + dataConfig("Message.rankTagRenameClose", "&7[&3PRISON INFO&7] &3Input &cclose &3to cancel or wait &c30 seconds&3."); + dataConfig("Message.rankTagRenameClosed", "&7[&3PRISON INFO&7] &cRename tag closed, nothing got changed!"); + dataConfig("Message.rankGuiDisabledOrAllGuiDisabled", "&7[&3PRISON INFO&7] &cGUI and/or GUI ranks is not enabled. Check GuiConfig.yml (%s %s)"); + dataConfig("Message.rankGuiMissingPermission", "&7[&3PRISON INFO&7] &cYou lack the permissions to use GUI ranks"); + dataConfig("Message.SellAllIsDisabled", "&7[&3PRISON ERROR&7] &cSorry but the SellAll Feature's disabled in the config.yml"); + dataConfig("Message.SellAllEditedWithSuccess", "] edited with success!"); + dataConfig("Message.SellAllSubCommandNotFound", "&7[&3PRISON WARN&7] &cSub-command not found, check with /sellall for a list!"); + dataConfig("Message.SellAllMultipliersAreDisabled", "&7[&3PRISON WARN&7] &cMultipliers are disabled in the SellAll config!"); + dataConfig("Message.SellAllMultiplierWrongFormat", "&7[&3PRISON WARN&7] &cWrong format, please use /sellall multiplier add/delete "); + dataConfig("Message.SellAllMissingPermission", "&7[&3PRISON WARN&7] &cSorry, but you don't have the permission ["); + dataConfig("Message.SellAllMissingPermissionToToggleAutoSell", "&7[&3PRISON WARN&7] &cSorry but you're missing the permission to use that! "); + dataConfig("Message.SellAllRanksDisabled", "&7[&3PRISON ERROR&7] &cThe Ranks module's disabled or not found!"); + dataConfig("Message.SellAllPrestigeLadderNotFound", "&7[&3PRISON WARN&7] &cCan't find the prestiges ladder, they might be disabled in the config.yml!"); + dataConfig("Message.SellAllCantFindPrestigeOrRank", "&7[&3PRISON WARN&7] &cCan't find the Prestige/Rank: "); + dataConfig("Message.SellAllRankNotFoundInPrestigeLadder", "&7[&3PRISON WARN&7] &cThe -prestiges- ladder doesn't contain the Rank: "); + dataConfig("Message.SellAllMultiplierNotANumber", "&7[&3PRISON WARN&7] &cSorry but the multiplier isn't a number!"); + dataConfig("Message.SellAllMultiplierNotNumber2", " Here-> "); + dataConfig("Message.SellAllConfigSaveFail", "&7[&3PRISON ERROR&7] &cSorry, something went wrong while saving the config!"); + dataConfig("Message.SellAllMultiplierEditSaveSuccess", "&7[&3PRISON&7] &aMultiplier got added or edited with success!"); + dataConfig("Message.SellAllMultiplierFormat", "&7[&3PRISON WARN&7] &cPlease use this format: /sellall multiplier delete "); + dataConfig("Message.SellAllCantFindMultiplier", "&7[&3PRISON WARN&7] &cCan't find the Multiplier of the prestige "); + dataConfig("Message.SellAllCantFindMultiplier2", " in the sellallconfig.yml"); + dataConfig("Message.SellAllMultiplierDeleteSuccess", "&7[&3PRISON WARN&7] &aMultiplier deleted with success!"); + dataConfig("Message.SellAllWrongFormatCommand", "&7[&3PRISON WARN&7] &cWrong format, try /sellall for a list of commands."); + dataConfig("Message.SellAllPleaseAddItem", "&7[&3PRISON WARN&7] &cPlease add an ITEM_ID [example: /sellall add COAL_ORE ]"); + dataConfig("Message.SellAllAddPrice", "&7[&3PRISON WARN&7] &cPlease add a price or value for the item [example: /sellall add COAL_ORE 100]"); + dataConfig("Message.SellAllWrongID", "&7[&3PRISON WARN&7] &cSorry but the ITEM_ID's wrong, please check it!"); + dataConfig("Message.SellAllValueNotNumber", "&7[&3PRISON WARN&7] &cSorry but the value isn't a number!"); + dataConfig("Message.SellAllMissingID", "&7[&3PRISON WARN&7] &cPlease add an ITEM_ID [example: /sellall delete COAL_ORE]"); + dataConfig("Message.SellAllTagWarn", "&7[&3PRISON WARN&7] &c"); + dataConfig("Message.SellAllNotFoundStringConfig", " not found in the config or got already deleted"); + dataConfig("Message.SellAllPrisonTag", "&7[&3PRISON&7]&a "); + dataConfig("Message.SellAllDeletedSuccess", " Deleted with success!"); + dataConfig("Message.SellAllAddSuccess", "]&a added with success!"); + dataConfig("Message.SellAllCommandEditSuccess", "]&a edited with success!"); + dataConfig("Message.SellAllYouArentPlayer", "&7[&3PRISON ERROR&7]&c You aren't a player"); + dataConfig("Message.SellAllNothingToSell", "&7[&3PRISON&7]&c You have nothing to sell!"); + dataConfig("Message.SellAllYouGotMoney", "&7[&3PRISON&7]&a You got $"); + dataConfig("Message.SellAllGUIDisabled", "&7[&3PRISON ERROR&7] &cSorry but the GUI's disabled in the SellAllConfig.yml"); + dataConfig("Message.SellAllAutoSell", "&7[&3PRISON INFO&7] Your inventory's full, AutoSell activated!"); + dataConfig("Message.SellAllSignNotify", "&7[&3PRISON&7] &aUsing SellAll from a sign with success!"); + dataConfig("Message.SellAllEmpty", "&7[&3PRISON ERROR&7] &cThere aren't items in the sellall config,\n please add them and maybe restart the server, this might need it sometimes!"); + dataConfig("Message.SellAllAutoEnabled", "&7[&3PRISON&7] &3SellAll-Auto &aenabled &3with success!"); + dataConfig("Message.SellAllAutoDisabled", "&7[&3PRISON&7] &3SellAll-Auto &cdisabled &3with success!"); + dataConfig("Setup.Message.MissingPermission", "&7[&3PRISON ERROR&7] &cSorry but you don't have the permission [-prison.setup- or -prison.admin-]!"); + dataConfig("Setup.Message.WrongFormat", "&7[&3PRISON ERROR&7] &cYou're missing the last argument -mines- or -ranks-, / setup -mines- or -ranks- !"); + dataConfig("Setup.Message.WelcomeToRanksSetup", "&7[&3PRISON INFO&7] &3Hi and welcome to the ranks setup, please wait until it'll be completed!"); + dataConfig("Setup.Message.SuccessRanksSetup", "&7[&3PRISON INFO&7] &3The ranks setup got completed with &asuccess&3 and the ranks got added to the default ladder,\n please check the logs if something's missing!"); + dataConfig("Setup.Message.Aborted", "&7[&3PRISON INFO&7] &3Prison Setup Cancelled."); } public FileConfiguration getFileGuiMessagesConfig(){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java index 82836f56a..717556f48 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java @@ -20,16 +20,12 @@ public class SellAllConfig extends SpigotConfigComponents { public SellAllConfig(){ - // Do not use requireNonNull. Should never throw an exception if they don't have - // it configured. - if ( Prison.get().getPlatform().getConfigBooleanFalse( "sellall" ) ) { - - initialize(); - } - + //if ( Prison.get().getPlatform().getConfigBooleanFalse("sellall")) { + initialize(); + //} } - private void initialize(){ + public void initialize(){ // Filepath File file = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); @@ -52,6 +48,8 @@ private void initialize(){ Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + "used by the SellAllConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage() ); } } + + conf = YamlConfiguration.loadConfiguration(file); } public void dataConfig(String key, String value){ @@ -74,8 +72,14 @@ private void values(){ dataConfig("Options.Player_GUI_Enabled","true"); dataConfig("Options.Player_GUI_Permission_Enabled","false"); dataConfig("Options.Player_GUI_Permission","prison.sellall.playergui"); + dataConfig("Options.Full_Inv_AutoSell", "false"); + dataConfig("Options.Full_Inv_AutoSell_Notification", "true"); + dataConfig("Options.Full_Inv_AutoSell_perUserToggleable", "false"); + dataConfig("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm", "false"); + dataConfig("Options.Full_Inv_AutoSell_PerUserToggleable_Permission", "prison.sellall.toggle"); dataConfig("Options.Multiplier_Enabled", "false"); dataConfig("Options.Multiplier_Default", "1"); + dataConfig("Options.Multiplier_Permission_Only_Higher", "false"); dataConfig("Options.Multiplier_Command_Permission_Enabled", "true"); dataConfig("Options.Multiplier_Command_Permission", "prison.admin"); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java index 4d40bebd0..da58c80ff 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java @@ -18,5 +18,4 @@ protected void fileMaker(File file) { } } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java new file mode 100644 index 000000000..edb653cf6 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java @@ -0,0 +1,141 @@ +package tech.mcprison.prison.spigot.customblock; + +import java.util.ArrayList; +import java.util.List; + +import com.jojodmo.customitems.api.CustomItemsAPI; + +import tech.mcprison.prison.integration.CustomBlockIntegration; +import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; + +/** + * Custom Items 3.7.11 — New API features +This version adds two new features to the Custom Items API: listCustomItemIDs and listBlockCustomItemIDs + * + */ +public class CustomItems + extends CustomBlockIntegration { + + private CustomItemsWrapper customItemsWrapper; + + public CustomItems() { + super("CustomItems", "CustomItems", PrisonBlockType.CustomItems, "cui:" ); + } + + @Override + public void integrate() { + + BluesSpigetSemVerComparator semVer = new BluesSpigetSemVerComparator(); + + if ( isRegistered()) { + try { + + if ( semVer.compareTo( getVersion(), "3.7.11" ) >= 0 ) { + + if ( CustomItemsAPI.isEnabled() ) { + + this.customItemsWrapper = new CustomItemsWrapper(); + + List prisonBlocks = getCustomBlockList(); + for ( PrisonBlock block : prisonBlocks ) + { + Output.get().logInfo( "#### Custom Block: " + block.toString() ); + } + } + } + else { + Output.get().logWarn( + String.format( "&cWarning: &3The plugin &7CustomItems v%s &3is enabled, " + + "but is too old and is not supported. Must " + + "use at least &7v3.7.11 &3or newer.", getVersion() ) ); + } + + } + catch ( NoClassDefFoundError | IllegalStateException e ) { + // ignore this exception since it means the plugin was not loaded + } + catch ( Exception e ) { + e.printStackTrace(); + } + } + + } + + + @Override + public boolean hasIntegrated() { + return (customItemsWrapper != null); + } + + @Override + public String getCustomBlockId( Block block ) { + return customItemsWrapper.getCustomBlockId( block ); + } + + /** + *

This function is supposed to identify if the given block is a custom block, and + * if it is a custom block, then this function will return the correct PrisonBlock + * to match it's type. The PrisonBlock that will be returned, will come from the + * collection of valid blocks that were generated upon server startup. + *

+ * + *

If there is no match, then this function will return a null. + *

+ * + *

It's also important to know that the original block that is retrieved from + * PrisonBlockTypes.getBlockTypesByName() is cloned prior to returning it to this + * function, so it's safe to do anything you want with it. + *

+ * + * @param block + * @return The matched and cloned PrisonBlock, otherwise it will return a null if no match. + */ + @Override + public PrisonBlock getCustomBlock( Block block ) { + PrisonBlock results = null; + + String customBlockId = getCustomBlockId( block ); + + if ( customBlockId != null ) { + results = SpigotPrison.getInstance().getPrisonBlockTypes() + .getBlockTypesByName( customBlockId ); + } + + return results; + } + + @Override + public Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ) { + return customItemsWrapper.setCustomBlockId( block, customId, doBlockUpdate ); + } + + @Override + public List getCustomBlockList() + { + List results = new ArrayList<>(); + + for ( String block : customItemsWrapper.getCustomBlockList() ) { + + PrisonBlock prisonBlock = new PrisonBlock( getBlockType(), block ); + + prisonBlock.setValid( true ); + prisonBlock.setBlock( true ); + + results.add( prisonBlock ); + } + + return results; + } + + + + @Override + public String getPluginSourceURL() { + return "https://polymart.org/resource/custom-items.1"; + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java new file mode 100644 index 000000000..7e714dd5b --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java @@ -0,0 +1,33 @@ +package tech.mcprison.prison.spigot.customblock; + +import java.util.List; + +import com.jojodmo.customitems.api.CustomItemsAPI; + +import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.spigot.block.SpigotBlock; + +public class CustomItemsWrapper { + + public CustomItemsWrapper() { + + } + + public String getCustomBlockId( Block block ) { + + org.bukkit.block.Block spigotBlock = ((SpigotBlock) block).getWrapper(); + CustomItemsAPI.getCustomItemIDAtBlock( spigotBlock ); + return null; + } + + public Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ) { + + org.bukkit.block.Block spigotBlock = ((SpigotBlock) block).getWrapper(); + org.bukkit.block.Block resultBlock = CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, customId, doBlockUpdate ); + return new SpigotBlock( resultBlock ); + } + + public List getCustomBlockList() { + return CustomItemsAPI.listBlockCustomItemIDs(); + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java index 9c943b7fa..8d20c8e15 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.spigot.game; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -133,4 +135,24 @@ public Inventory getInventory() { public void printDebugInventoryInformationToConsole() { } + + @Override + public List getPermissions() { + List results = new ArrayList<>(); + + return results; + } + + @Override + public List getPermissions( String prefix ) { + List results = new ArrayList<>(); + + for ( String perm : getPermissions() ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java index 792f9b0f6..8add8f911 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java @@ -21,12 +21,16 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.permissions.PermissionAttachmentInfo; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; @@ -119,6 +123,32 @@ public org.bukkit.entity.Player getWrapper() { bukkitPlayer.updateInventory(); } + @Override + public List getPermissions() { + List results = new ArrayList<>(); + + Set perms = bukkitPlayer.getEffectivePermissions(); + for ( PermissionAttachmentInfo perm : perms ) + { + results.add( perm.getPermission() ); + } + + return results; + } + + @Override + public List getPermissions( String prefix ) { + List results = new ArrayList<>(); + + for ( String perm : getPermissions() ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; + } + /** * This class is an adaptation of the NmsHelper class in the Rosetta library by Max Roncace. The * library is licensed under the New BSD License. See the {@link tech.mcprison.prison.localization} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index 5fda3d537..6653b9962 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -5,8 +5,10 @@ import java.util.List; import java.util.Optional; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.block.Sign; import org.bukkit.configuration.Configuration; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -14,11 +16,14 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerInteractEvent; import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; @@ -112,6 +117,101 @@ public void addChatEventPlayer(Player p){ } } + @EventHandler + public void onSignEditing(SignChangeEvent e){ + + // Check if the feature's enabled + if (!(config.getString("sellall-sign").equalsIgnoreCase("true"))){ + return; + } + + Player p = e.getPlayer(); + String signTag = config.getString("sellall-sign-visible-tag"); + if (signTag == null){ + signTag = "&7[&3SellAll&7]"; + } + + try { + if (e.getLine(0).equalsIgnoreCase("[SellAll]") || e.getLine(0).equalsIgnoreCase(signTag)) { + if (p.hasPermission("prison.sign")){ + e.setLine(0, SpigotPrison.format(signTag)); + } else { + e.setLine(0, SpigotPrison.format("&cNo perm")); + e.setLine(1, SpigotPrison.format("prison.sign")); + } + } + } catch (IndexOutOfBoundsException ignored){} + } + + @EventHandler + public void onPlayerClickSign(PlayerInteractEvent e){ + + // Check if the feature's enabled + if (!(config.getString("sellall-sign").equalsIgnoreCase("true"))){ + return; + } + + Material clickedBlock; + Material signMaterial; + Material signWallMaterial; + + // Check if the clickedBlock's a block + try { + clickedBlock = e.getClickedBlock().getType(); + } catch (NullPointerException ex){ + return; + } + + // Not sure which one will work better + try { + signMaterial = XMaterial.matchXMaterial(Material.SIGN).parseItem().getType(); + } catch (NullPointerException ex) { + signMaterial = XMaterial.matchXMaterial(Material.SIGN).parseMaterial(); + } + try { + signWallMaterial = XMaterial.matchXMaterial(Material.WALL_SIGN).parseItem().getType(); + } catch (NullPointerException ex){ + signWallMaterial = XMaterial.matchXMaterial(Material.WALL_SIGN).parseMaterial(); + } + + + // Check if the clicked block's a sign + if (clickedBlock == signMaterial || clickedBlock == signWallMaterial){ + + // Get the player + Player p = e.getPlayer(); + String signTag = config.getString("sellall-sign-visible-tag"); + if (signTag == null) { + signTag = "&7[&3SellAll&7]"; + } + + // Get the action + Action action = e.getAction(); + + // Check if the action's a click + if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK){ + + // Get sign + Sign sign = (Sign) e.getClickedBlock().getState(); + + // If there aren't lines in the sign this will void an error + try { + + // Check if the first like of the sign have the right tag + if (sign.getLine(0).equalsIgnoreCase(SpigotPrison.format(signTag))){ + + if (config.getString("sellall-sign-notify").equalsIgnoreCase("true")){ + p.sendMessage(SpigotPrison.format(messages.getString("Message.SellAllSignNotify"))); + } + + // Execute the sellall command + Bukkit.dispatchCommand(p, "sellall sell"); + } + } catch (IndexOutOfBoundsException ignored){} + } + } + } + public void removeChatEventPlayer(Player p){ chatEventPlayer.remove(p.getName()); } @@ -462,7 +562,7 @@ public void onClick(InventoryClickEvent e){ } // Check the title and do the actions - case "PrisonManager -> SellAll-Admin":{ + case "Prison -> SellAll-Admin":{ sellAllAdminGUI(e, p, buttonNameMain); @@ -478,7 +578,7 @@ public void onClick(InventoryClickEvent e){ } // Check the title and do the actions - case "PrisonManager -> SellAll-Player":{ + case "Prison -> SellAll-Player":{ p.closeInventory(); e.setCancelled(true); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java index 0b43b2fcb..3ae9ebefb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java @@ -1,7 +1,7 @@ package tech.mcprison.prison.spigot.gui; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -64,8 +64,8 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToCancel")); // Create the button, set up the material, amount, lore and name - ItemStack confirm = createButton(Material.EMERALD_BLOCK, 1, confirmLore, SpigotPrison.format("&3" + "Confirm: Setup")); - ItemStack cancel = createButton(Material.REDSTONE_BLOCK, 1, cancelLore, SpigotPrison.format("&3" + "Cancel: Setup")); + ItemStack confirm = createButton(XMaterial.EMERALD_BLOCK.parseItem(), confirmLore, SpigotPrison.format("&3" + "Confirm: Setup")); + ItemStack cancel = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), cancelLore, SpigotPrison.format("&3" + "Cancel: Setup")); // Position of the button inv.setItem(2, confirm); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIComponents.java index 57aadb16b..de64e1c71 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIComponents.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; @@ -25,6 +26,10 @@ public abstract class SpigotGUIComponents { // createButton method (create a button for the GUI - item) protected ItemStack createButton(Material id, int amount, List lore, String display) { + if (id == null){ + id = XMaterial.BARRIER.parseMaterial(); + } + ItemStack item = new ItemStack(id, amount); ItemMeta meta = item.getItemMeta(); if ( meta != null ) { @@ -39,8 +44,17 @@ protected ItemStack createButton(Material id, int amount, List lore, Str return item; } protected ItemStack createButton(ItemStack item, List lore, String display) { + + if (item == null){ + item = XMaterial.BARRIER.parseItem(); + } ItemMeta meta = item.getItemMeta(); + + if (meta == null){ + meta = XMaterial.BARRIER.parseItem().getItemMeta(); + } + if ( meta != null ) { meta.setDisplayName(SpigotPrison.format(display)); try { @@ -95,5 +109,4 @@ protected void openGUI(Player p, Inventory inv){ p.openInventory(inv); ListenersPrisonManager.get().addToGUIBlocker(p); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java index d0bb6d744..5d1d137c0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java @@ -3,7 +3,6 @@ import java.util.List; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -69,10 +68,10 @@ private void buttonsSetup(Inventory inv) { ItemStack closeGUI = createButton(XMaterial.RED_STAINED_GLASS_PANE.parseItem(), closeGUILore, SpigotPrison.format("&c" + "Close")); // Create the button, set up the material, amount, lore and name - ItemStack ranks = createButton(Material.TRIPWIRE_HOOK, 1, ranksLore, SpigotPrison.format("&3" + "Ranks")); - ItemStack autoManager = createButton(Material.IRON_PICKAXE, 1, prisonTasksLore, SpigotPrison.format("&3" + "AutoManager")); - ItemStack mines = createButton(Material.DIAMOND_ORE, 1, minesLore, SpigotPrison.format("&3" + "Mines")); - ItemStack sellAll = createButton(Material.CHEST, 1 , sellAllLore, SpigotPrison.format("&3" + "SellAll")); + ItemStack ranks = createButton(XMaterial.TRIPWIRE_HOOK.parseItem(), ranksLore, SpigotPrison.format("&3" + "Ranks")); + ItemStack autoManager = createButton(XMaterial.IRON_PICKAXE.parseItem(), prisonTasksLore, SpigotPrison.format("&3" + "AutoManager")); + ItemStack mines = createButton(XMaterial.DIAMOND_ORE.parseItem(), minesLore, SpigotPrison.format("&3" + "Mines")); + ItemStack sellAll = createButton(XMaterial.CHEST.parseItem(), sellAllLore, SpigotPrison.format("&3" + "SellAll")); // Position of the button inv.setItem(10, ranks); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java index 5c1c5df44..187c9bd99 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java @@ -4,7 +4,6 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -13,7 +12,6 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -76,90 +74,90 @@ private void buttonsSetup(Inventory inv) { } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockGoldBlock ) ) { - ItemStack Enabled = createButton(Material.GOLD_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Gold_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.GOLD_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Gold_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.GOLD_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Gold_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.GOLD_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Gold_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockIronBlock ) ) { - ItemStack Enabled = createButton(Material.IRON_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Iron_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.IRON_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Iron_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.IRON_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Iron_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.IRON_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Iron_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockCoalBlock ) ) { - ItemStack Enabled = createButton(Material.COAL_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Coal_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.COAL_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Coal_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.COAL_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Coal_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.COAL_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Coal_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockDiamondBlock ) ) { - ItemStack Enabled = createButton(Material.DIAMOND_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Diamond_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.DIAMOND_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Diamond_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.DIAMOND_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Diamond_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.DIAMOND_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Diamond_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockRedstoneBlock ) ) { - ItemStack Enabled = createButton(Material.REDSTONE_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Redstone_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Redstone_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.REDSTONE_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Redstone_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Redstone_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockEmeraldBlock ) ) { - ItemStack Enabled = createButton(Material.EMERALD_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Emerald_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.EMERALD_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Emerald_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.EMERALD_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Emerald_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.EMERALD_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Emerald_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockQuartzBlock ) ) { - ItemStack Enabled = createButton(Material.QUARTZ_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Quartz_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.QUARTZ_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Quartz_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.QUARTZ_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Quartz_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.QUARTZ_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Quartz_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockPrismarineBlock ) ) { - ItemStack Enabled = createButton(Material.PRISMARINE, 1, enabledLore, SpigotPrison.format("&a" + "Prismarine_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.PRISMARINE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Prismarine_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.PRISMARINE, 1, disabledLore, SpigotPrison.format("&c" + "Prismarine_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.PRISMARINE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Prismarine_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockLapisBlock ) ) { - ItemStack Enabled = createButton(Material.LAPIS_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Lapis_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.LAPIS_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Lapis_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.LAPIS_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Lapis_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.LAPIS_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Lapis_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockSnowBlock ) ) { - ItemStack Enabled = createButton(Material.SNOW_BLOCK, 1, enabledLore, SpigotPrison.format("&a" + "Snow_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.SNOW_BLOCK.parseItem(), enabledLore, SpigotPrison.format("&a" + "Snow_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.SNOW_BLOCK, 1, disabledLore, SpigotPrison.format("&c" + "Snow_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.SNOW_BLOCK.parseItem(), disabledLore, SpigotPrison.format("&c" + "Snow_Block Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoBlockGlowstone ) ) { - ItemStack Enabled = createButton(Material.GLOWSTONE, 1, enabledLore, SpigotPrison.format("&a" + "Glowstone_Block Enabled")); + ItemStack Enabled = createButton(XMaterial.GLOWSTONE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Glowstone_Block Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.GLOWSTONE, 1, disabledLore, SpigotPrison.format("&c" + "Glowstone_Block Disabled")); + ItemStack Disabled = createButton(XMaterial.GLOWSTONE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Glowstone_Block Disabled")); inv.addItem(Disabled); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java index cb4553814..9a55128ee 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java @@ -13,7 +13,6 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java index 090c6882c..62a592794 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java @@ -11,7 +11,6 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -78,66 +77,66 @@ private void buttonsSetup(Inventory inv) { } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupCobbleStone ) ) { - ItemStack Enabled = createButton(Material.COBBLESTONE, 1, enabledLore, SpigotPrison.format("&a" + "Cobblestone Enabled")); + ItemStack Enabled = createButton(XMaterial.COBBLESTONE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Cobblestone Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.COBBLESTONE, 1, disabledLore, SpigotPrison.format("&c" + "Cobblestone Disabled")); + ItemStack Disabled = createButton(XMaterial.COBBLESTONE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Cobblestone Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupStone ) ) { - ItemStack Enabled = createButton(Material.STONE, 1, enabledLore, SpigotPrison.format("&a" + "Stone Enabled")); + ItemStack Enabled = createButton(XMaterial.STONE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Stone Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.STONE, 1, disabledLore, SpigotPrison.format("&c" + "Stone Disabled")); + ItemStack Disabled = createButton(XMaterial.STONE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Stone Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupGoldOre ) ) { - ItemStack Enabled = createButton(Material.GOLD_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.GOLD_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.GOLD_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.GOLD_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupIronOre ) ) { - ItemStack Enabled = createButton(Material.IRON_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.IRON_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.IRON_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.IRON_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupCoalOre ) ) { - ItemStack Enabled = createButton(Material.COAL_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Coal_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.COAL_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Coal_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.COAL_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Coal_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.COAL_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Coal_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupDiamondOre ) ) { - ItemStack Enabled = createButton(Material.DIAMOND_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Diamond_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.DIAMOND_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Diamond_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.DIAMOND_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Diamond_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.DIAMOND_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Diamond_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupRedStoneOre ) ) { - ItemStack Enabled = createButton(Material.REDSTONE_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Redstone_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.REDSTONE_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Redstone_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.REDSTONE_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Redstone_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.REDSTONE_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Redstone_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupEmeraldOre ) ) { - ItemStack Enabled = createButton(Material.EMERALD_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Emerald_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.EMERALD_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Emerald_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.EMERALD_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Emerald_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.EMERALD_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Emerald_Ore Disabled")); inv.addItem(Disabled); } @@ -154,10 +153,10 @@ private void buttonsSetup(Inventory inv) { } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupLapisOre ) ) { - ItemStack Enabled = createButton(Material.LAPIS_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Lapis_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.LAPIS_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Lapis_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.LAPIS_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Lapis_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.LAPIS_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Lapis_Ore Disabled")); inv.addItem(Disabled); } @@ -174,10 +173,10 @@ private void buttonsSetup(Inventory inv) { } if ( afConfig.isFeatureBoolean( AutoFeatures.autoPickupGlowstoneDust ) ) { - ItemStack Enabled = createButton(Material.GLOWSTONE_DUST, 1, enabledLore, SpigotPrison.format("&a" + "Glowstone_Dust Enabled")); + ItemStack Enabled = createButton(XMaterial.GLOWSTONE_DUST.parseItem(), enabledLore, SpigotPrison.format("&a" + "Glowstone_Dust Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.GLOWSTONE_DUST, 1, disabledLore, SpigotPrison.format("&c" + "Glowstone_Dust Disabled")); + ItemStack Disabled = createButton(XMaterial.GLOWSTONE_DUST.parseItem(), disabledLore, SpigotPrison.format("&c" + "Glowstone_Dust Disabled")); inv.addItem(Disabled); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java index e48e937c5..f4d33781a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java @@ -2,7 +2,6 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -11,7 +10,6 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -75,18 +73,18 @@ private void buttonsSetup(Inventory inv) { } if ( afConfig.isFeatureBoolean( AutoFeatures.autoSmeltGoldOre ) ) { - ItemStack Enabled = createButton(Material.GOLD_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.GOLD_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.GOLD_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.GOLD_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled")); inv.addItem(Disabled); } if ( afConfig.isFeatureBoolean( AutoFeatures.autoSmeltIronOre ) ) { - ItemStack Enabled = createButton(Material.IRON_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled")); + ItemStack Enabled = createButton(XMaterial.IRON_ORE.parseItem(), enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled")); inv.addItem(Enabled); } else { - ItemStack Disabled = createButton(Material.IRON_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled")); + ItemStack Disabled = createButton(XMaterial.IRON_ORE.parseItem(), disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled")); inv.addItem(Disabled); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java index e451ca6b8..61fc681a6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java @@ -13,9 +13,9 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; public class SpigotBlocksListGUI extends SpigotGUIComponents { @@ -47,7 +47,9 @@ public void open(){ ); // This will skip all BlockTypes that are invalid for the versions of MC that the server is running: - List blockTypes = Prison.get().getPrisonBlockTypes().getBlockTypes(); + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + + List blockTypes = prisonBlockTypes.getBlockTypes(); // Only loop over the blocks that we need to show: int i = counter; @@ -80,39 +82,6 @@ public void open(){ "&7Prior &0" + mineName + " " + (i - (pageSize * 2) - 1) ); inv.setItem(51, priorPageButton); } - - -// for (PrisonBlock prisonBlock : blockTypes){ -// -// BlockType block = SpigotUtil.prisonBlockToBlockType( prisonBlock ); -// -// try { -// if (secondCounter >= counter) { -// Material material = ( block == BlockType.IGNORE ? -// Material.BARRIER : SpigotUtil.getXMaterial( block ).parseMaterial() ); -// if ( material == null ) { -// material = XMaterial.STONE.parseMaterial(); -// } -// ItemStack button = createButton(material, 1, blockLoreSetup, SpigotPrison.format("&a" + block.name().toUpperCase() + " " + mineName)); -// inv.addItem(button); -// } -// } catch (NullPointerException ignored){} -// -// secondCounter++; -// counter++; -// -// if (counter >= counter + 44){ -// -// List nextPageLore = createLore( -// messages.getString("Lore.ClickToNextPage") -// ); -// -// ItemStack nextPageButton = createButton(Material.BOOK, 1, nextPageLore, "Next " + mineName + " " + counter); -// inv.setItem(53, nextPageButton); -// -// } -// -// } // Open the inventory openGUI(p, inv); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java index 630de9709..b529b4ed4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java @@ -12,7 +12,6 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -76,17 +75,19 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToIncrease") ); + Material decreaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack decreaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); // Decrease button - ItemStack decreaseOf1 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 1" + " &0" + counter)); + ItemStack decreaseOf1 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 1" + " &0" + counter)); inv.setItem(1, decreaseOf1); - ItemStack decreaseOf5 = createButton(Material.REDSTONE_BLOCK, 5, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 5" + " &0" + counter)); + ItemStack decreaseOf5 = createButton(new ItemStack(decreaseMat, 5), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 5" + " &0" + counter)); inv.setItem(10, decreaseOf5); - ItemStack decreaseOf10 = createButton(Material.REDSTONE_BLOCK, 10, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 10" + " &0" + counter)); + ItemStack decreaseOf10 = createButton(new ItemStack(decreaseMat, 10), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 10" + " &0" + counter)); inv.setItem(19, decreaseOf10); - ItemStack decreaseOf50 = createButton(Material.REDSTONE_BLOCK, 50, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 50" + " &0" + counter)); + ItemStack decreaseOf50 = createButton(new ItemStack(decreaseMat, 50), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 50" + " &0" + counter)); inv.setItem(28, decreaseOf50); - ItemStack decreaseOf100 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 100" + " &0" + counter)); + ItemStack decreaseOf100 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " - 100" + " &0" + counter)); inv.setItem(37, decreaseOf100); @@ -100,17 +101,19 @@ private void buttonsSetup(Inventory inv) { ItemStack confirmButton = createButton(watch, 1, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + mineName + " " + blockName + " " + val + " &0" + counter)); inv.setItem(22, confirmButton); + Material increaseMat = XMaterial.EMERALD_BLOCK.parseMaterial(); + ItemStack increaseStack = XMaterial.EMERALD_BLOCK.parseItem(); // Increase button - ItemStack increseOf1 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 1" + " &0" + counter )); + ItemStack increseOf1 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 1" + " &0" + counter )); inv.setItem(7, increseOf1); - ItemStack increaseOf5 = createButton(Material.EMERALD_BLOCK, 5, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 5" + " &0" + counter)); + ItemStack increaseOf5 = createButton(new ItemStack(increaseMat, 5), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 5" + " &0" + counter)); inv.setItem(16, increaseOf5); - ItemStack increaseOf10 = createButton(Material.EMERALD_BLOCK, 10, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 10" + " &0" + counter)); + ItemStack increaseOf10 = createButton(new ItemStack(increaseMat, 10), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 10" + " &0" + counter)); inv.setItem(25, increaseOf10); - ItemStack increaseOf50 = createButton(Material.EMERALD_BLOCK, 50, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 50" + " &0" + counter)); + ItemStack increaseOf50 = createButton(new ItemStack(increaseMat, 50), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 50" + " &0" + counter)); inv.setItem(34, increaseOf50); - ItemStack increaseOf100 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 100" + " &0" + counter)); + ItemStack increaseOf100 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + blockName + " " + val + " + 100" + " &0" + counter)); inv.setItem(43, increaseOf100); // Return to prior screen: diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java index a11b559f7..c1125a399 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java @@ -12,7 +12,6 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -99,9 +98,9 @@ private void buttonsSetup(Inventory inv) { // Create the button, set the material, amount, lore and name ItemStack closeGUI = createButton(XMaterial.RED_STAINED_GLASS_PANE.parseItem(), closeGUILore, SpigotPrison.format("&c" + "Close")); - ItemStack resetMine = createButton(Material.EMERALD_BLOCK, 1, resetMineLore, SpigotPrison.format("&3" + "Reset_Mine: " + mineName)); - ItemStack MineSpawn = createButton(Material.COMPASS, 1, MineSpawnLore, SpigotPrison.format("&3" + "Mine_Spawn: " + mineName)); - ItemStack MinesNotifications = createButton(Material.SIGN, 1, MinesNotificationsLore, SpigotPrison.format("&3" + "Mine_notifications: " + mineName)); + ItemStack resetMine = createButton(XMaterial.EMERALD_BLOCK.parseItem(), resetMineLore, SpigotPrison.format("&3" + "Reset_Mine: " + mineName)); + ItemStack MineSpawn = createButton(XMaterial.COMPASS.parseItem(), MineSpawnLore, SpigotPrison.format("&3" + "Mine_Spawn: " + mineName)); + ItemStack MinesNotifications = createButton(new ItemStack(Material.SIGN, 1), MinesNotificationsLore, SpigotPrison.format("&3" + "Mine_notifications: " + mineName)); // Create the button Material bed = Material.matchMaterial( "bed" ); @@ -111,7 +110,7 @@ private void buttonsSetup(Inventory inv) { ItemStack MinesTP = createButton(bed, 1, MinesTpLore, SpigotPrison.format("&3" + "TP_to_the_Mine: " + mineName)); // Create the button, set up the material, amount, lore and name - ItemStack blocksOfTheMine = createButton(Material.COAL_ORE, 1, blocksOfTheMineLore, SpigotPrison.format("&3" + "Blocks_of_the_Mine: " + mineName)); + ItemStack blocksOfTheMine = createButton(XMaterial.COAL_ORE.parseItem(), blocksOfTheMineLore, SpigotPrison.format("&3" + "Blocks_of_the_Mine: " + mineName)); // Create the button, set up the material, amount, lore and name Material watch = Material.matchMaterial( "watch" ); @@ -122,7 +121,7 @@ private void buttonsSetup(Inventory inv) { } ItemStack mineResetTime = createButton(watch, 1, mineResetTimeLore, SpigotPrison.format("&3" + "Reset_Time: " + mineName)); - ItemStack mineRename = createButton(Material.FEATHER, 1, mineRenameLore, SpigotPrison.format("&3" + "Mine_Name: " + mineName)); + ItemStack mineRename = createButton(XMaterial.FEATHER.parseItem(), mineRenameLore, SpigotPrison.format("&3" + "Mine_Name: " + mineName)); // Position of the button inv.setItem(10, resetMine); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java index 159cb09d1..7bb29c677 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.gui.mine; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.Configuration; @@ -7,7 +8,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -69,16 +69,19 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToIncrease") ); + Material decreaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack decreaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); + // Decrease buttons - ItemStack decreaseOf1 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 1 " + typeNotification )); + ItemStack decreaseOf1 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 1 " + typeNotification )); inv.setItem(1, decreaseOf1); - ItemStack decreaseOf5 = createButton(Material.REDSTONE_BLOCK, 5, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 5 " + typeNotification)); + ItemStack decreaseOf5 = createButton(new ItemStack(decreaseMat, 5), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 5 " + typeNotification)); inv.setItem(10, decreaseOf5); - ItemStack decreaseOf10 = createButton(Material.REDSTONE_BLOCK, 10, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 10 " + typeNotification)); + ItemStack decreaseOf10 = createButton(new ItemStack(decreaseMat, 10), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 10 " + typeNotification)); inv.setItem(19, decreaseOf10); - ItemStack decreaseOf50 = createButton(Material.REDSTONE_BLOCK, 50, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 50 " + typeNotification)); + ItemStack decreaseOf50 = createButton(new ItemStack(decreaseMat, 50), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 50 " + typeNotification)); inv.setItem(28, decreaseOf50); - ItemStack decreaseOf100 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 100 " + typeNotification)); + ItemStack decreaseOf100 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 100 " + typeNotification)); inv.setItem(37, decreaseOf100); @@ -92,18 +95,19 @@ private void buttonsSetup(Inventory inv) { ItemStack confirmButton = createButton(watch, 1, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + mineName + " " + val + " " + typeNotification)); inv.setItem(22, confirmButton); + Material increaseMat = XMaterial.EMERALD_BLOCK.parseMaterial(); + ItemStack increaseStack = XMaterial.EMERALD_BLOCK.parseItem(); // Increase buttons - ItemStack increseOf1 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 1 " + typeNotification)); - inv.setItem(7, increseOf1); - ItemStack increaseOf5 = createButton(Material.EMERALD_BLOCK, 5, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 5 " + typeNotification)); + ItemStack increaseOf1 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 1 " + typeNotification)); + inv.setItem(7, increaseOf1); + ItemStack increaseOf5 = createButton(new ItemStack(increaseMat, 5), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 5 " + typeNotification)); inv.setItem(16, increaseOf5); - ItemStack increaseOf10 = createButton(Material.EMERALD_BLOCK, 10, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 10 " + typeNotification)); + ItemStack increaseOf10 = createButton(new ItemStack(increaseMat, 10), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 10 " + typeNotification)); inv.setItem(25, increaseOf10); - ItemStack increaseOf50 = createButton(Material.EMERALD_BLOCK, 50, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 50 " + typeNotification)); + ItemStack increaseOf50 = createButton(new ItemStack(increaseMat, 50), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 50 " + typeNotification)); inv.setItem(34, increaseOf50); - ItemStack increaseOf100 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 100 " + typeNotification)); + ItemStack increaseOf100 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 100 " + typeNotification)); inv.setItem(43, increaseOf100); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java index 12027bae0..5b34d8e16 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java @@ -11,7 +11,6 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -97,7 +96,7 @@ private void buttonsSetup(Inventory inv, String enabledOrDisabled) { } // Create a button - ItemStack modeWithin = createButton(Material.IRON_DOOR, 1, modeWithinLore, SpigotPrison.format("&3Within_Mode: " + mineName)); + ItemStack modeWithin = createButton(XMaterial.IRON_DOOR.parseItem(), modeWithinLore, SpigotPrison.format("&3Within_Mode: " + mineName)); // Create a button Material fence = Material.matchMaterial( "fence" ); @@ -107,7 +106,7 @@ private void buttonsSetup(Inventory inv, String enabledOrDisabled) { ItemStack radiusMode = createButton(fence, 1, modeRadiusLore, SpigotPrison.format("&3Radius_Mode: " + mineName)); // Create a button - ItemStack disabledMode = createButton(Material.REDSTONE_BLOCK, 1, disabledModeLore, SpigotPrison.format("&3Disabled_Mode: " + mineName)); + ItemStack disabledMode = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), disabledModeLore, SpigotPrison.format("&3Disabled_Mode: " + mineName)); // Check which buttons should be added, based on the mode already in use of the Mine Notifications if (enabledOrDisabled.equalsIgnoreCase("disabled")){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java index 2f1fc94d1..1d4bf41b9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.gui.mine; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.Configuration; @@ -7,7 +8,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -67,16 +67,19 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToIncrease") ); + Material decreaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack decreaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); + // Decrease button - ItemStack decreaseOf1 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 1" )); + ItemStack decreaseOf1 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 1" )); inv.setItem(1, decreaseOf1); - ItemStack decreaseOf5 = createButton(Material.REDSTONE_BLOCK, 5, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 5")); + ItemStack decreaseOf5 = createButton(new ItemStack(decreaseMat, 5), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 5")); inv.setItem(10, decreaseOf5); - ItemStack decreaseOf10 = createButton(Material.REDSTONE_BLOCK, 10, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 10")); + ItemStack decreaseOf10 = createButton(new ItemStack(decreaseMat, 10), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 10")); inv.setItem(19, decreaseOf10); - ItemStack decreaseOf50 = createButton(Material.REDSTONE_BLOCK, 50, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 50")); + ItemStack decreaseOf50 = createButton(new ItemStack(decreaseMat, 50), changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 50")); inv.setItem(28, decreaseOf50); - ItemStack decreaseOf100 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 100")); + ItemStack decreaseOf100 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " - 100")); inv.setItem(37, decreaseOf100); // Create a button and set the position @@ -89,16 +92,19 @@ private void buttonsSetup(Inventory inv) { ItemStack confirmButton = createButton(watch, 1, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + mineName + " " + val)); inv.setItem(22, confirmButton); + Material increaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack increaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); + // Increase button - ItemStack increseOf1 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 1" )); - inv.setItem(7, increseOf1); - ItemStack increaseOf5 = createButton(Material.EMERALD_BLOCK, 5, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 5")); + ItemStack increaseOf1 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 1" )); + inv.setItem(7, increaseOf1); + ItemStack increaseOf5 = createButton(new ItemStack(increaseMat, 5), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 5")); inv.setItem(16, increaseOf5); - ItemStack increaseOf10 = createButton(Material.EMERALD_BLOCK, 10, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 10")); + ItemStack increaseOf10 = createButton(new ItemStack(increaseMat, 10), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 10")); inv.setItem(25, increaseOf10); - ItemStack increaseOf50 = createButton(Material.EMERALD_BLOCK, 50, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 50")); + ItemStack increaseOf50 = createButton(new ItemStack(increaseMat, 50), changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 50")); inv.setItem(34, increaseOf50); - ItemStack increaseOf100 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 100")); + ItemStack increaseOf100 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + mineName + " " + val + " + 100")); inv.setItem(43, increaseOf100); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java index b3130f525..cbe60700b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java @@ -16,7 +16,6 @@ import tech.mcprison.prison.mines.data.Block; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -147,7 +146,7 @@ private void buttonsSetup(Inventory inv, PrisonBlock block, String blockmaterial blockslore.add(SpigotPrison.format(messages.getString("Lore.BlockType") + blockmaterial)); // Make the item - ItemStack block1 = createButton(Material.valueOf(blockmaterial), 1, blockslore, SpigotPrison.format("&3" + blockmaterialdisplay + " " + mineName + " " + block.getChance())); + ItemStack block1 = createButton(XMaterial.valueOf(blockmaterial).parseItem(), blockslore, SpigotPrison.format("&3" + blockmaterialdisplay + " " + mineName + " " + block.getChance())); inv.addItem(block1); } @@ -178,7 +177,7 @@ private void buttonsSetup(Inventory inv, Block block, String blockmaterial, Stri blockslore.add(SpigotPrison.format(messages.getString("Lore.BlockType") + blockmaterial)); // Make the item - ItemStack block1 = createButton(Material.valueOf(blockmaterial), 1, blockslore, SpigotPrison.format("&3" + blockmaterialdisplay + " " + mineName + " " + block.getChance())); + ItemStack block1 = createButton(XMaterial.valueOf(blockmaterial).parseItem(), blockslore, SpigotPrison.format("&3" + blockmaterialdisplay + " " + mineName + " " + block.getChance())); // Add the item to the inventory inv.addItem(block1); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java index 8eddad3a9..3c501f933 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java @@ -1,13 +1,12 @@ package tech.mcprison.prison.spigot.gui.mine; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -53,14 +52,14 @@ private void buttonsSetup(Inventory inv) { // Blocks of the mine - List confirmlore = createLore( + List confirmLore = createLore( messages.getString("Lore.ClickToConfirm")); - List cancelore = createLore( + List cancelLore = createLore( messages.getString("Lore.ClickToCancel")); // Create the button, set up the material, amount, lore and name - ItemStack confirm = createButton(Material.EMERALD_BLOCK, 1, confirmlore, SpigotPrison.format("&3" + "Confirm: " + mineName)); - ItemStack cancel = createButton(Material.REDSTONE_BLOCK, 1, cancelore, SpigotPrison.format("&3" + "Cancel: " + mineName)); + ItemStack confirm = createButton(XMaterial.EMERALD_BLOCK.parseItem(), confirmLore, SpigotPrison.format("&3" + "Confirm: " + mineName)); + ItemStack cancel = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), cancelLore, SpigotPrison.format("&3" + "Cancel: " + mineName)); // Position of the button inv.setItem(2, confirm); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java index 65fad02e7..eb78568e1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java @@ -3,9 +3,9 @@ import java.text.DecimalFormat; import java.util.List; +import com.cryptomorin.xseries.XMaterial; import org.apache.commons.lang3.StringUtils; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -19,7 +19,6 @@ import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.PrisonSetupGUI; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; @@ -148,8 +147,7 @@ private void buttonsSetup(Inventory inv, Mine m) { } // Create the button - itemMines = createButton(Material.COAL_ORE, 1, minesLore, SpigotPrison.format("&3" + m.getName())); + itemMines = createButton(XMaterial.COAL_ORE.parseItem(), minesLore, SpigotPrison.format("&3" + m.getName())); inv.addItem(itemMines); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java index f40840347..1f74d90bd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java @@ -124,12 +124,12 @@ private void buttonsSetup(Inventory inv, Mine m, List minesLore) { minesLore.add(SpigotPrison.format(messages.getString("Lore.StatusUnlockedMine"))); minesLore.add(SpigotPrison.format(messages.getString("Lore.ClickToTeleport"))); } else { - material = Material.REDSTONE_BLOCK; + material = XMaterial.REDSTONE_BLOCK.parseMaterial(); minesLore.add(SpigotPrison.format(messages.getString("Lore.StatusLockedMine"))); } // Create the button - itemMines = createButton(material, 1, minesLore, SpigotPrison.format("&3" + m.getName())); + itemMines = createButton(new ItemStack(material, 1), minesLore, SpigotPrison.format("&3" + m.getName())); // Add the button to the inventory inv.addItem(itemMines); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java index a69d017b9..6791cd9cb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java @@ -1,13 +1,12 @@ package tech.mcprison.prison.spigot.gui.rank; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -59,8 +58,8 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToCancel")); // Create the button, set up the material, amount, lore and name - ItemStack confirm = createButton(Material.EMERALD_BLOCK, 1, confirmLore, SpigotPrison.format("&3" + "Confirm: Prestige")); - ItemStack cancel = createButton(Material.REDSTONE_BLOCK, 1, cancelLore, SpigotPrison.format("&3" + "Cancel: Don't Prestige")); + ItemStack confirm = createButton(XMaterial.EMERALD_BLOCK.parseItem(), confirmLore, SpigotPrison.format("&3" + "Confirm: Prestige")); + ItemStack cancel = createButton(XMaterial.REDSTONE_BLOCK.parseItem(), cancelLore, SpigotPrison.format("&3" + "Cancel: Don't Prestige")); // Position of the button inv.setItem(2, confirm); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java index aadd703a1..4edcbc354 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java @@ -2,8 +2,8 @@ import java.util.List; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -13,7 +13,6 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -94,7 +93,7 @@ private void buttonsSetup(Inventory inv, RankLadder ladder) { messages.getString("Lore.ShiftAndRightClickToDelete")); // Create the button - itemLadder = createButton(Material.LADDER, 1, laddersLore, SpigotPrison.format("&3" + ladder.name)); + itemLadder = createButton(XMaterial.LADDER.parseItem(), laddersLore, SpigotPrison.format("&3" + ladder.name)); // Add the button to the inventory inv.addItem(itemLadder); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index 06cbd9ba5..d99d05df2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.gui.rank; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Server; @@ -19,11 +20,9 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; -import java.util.Objects; import java.util.Optional; /** @@ -165,11 +164,11 @@ private void buttonsSetup(Optional ladder, int dimension, Inventory Rank rank = ladderData.getLowestRank().get(); - Rank playerRank = getRankPlayer().getRank( ladderData ).orElse( null ); + Rank playerRank = getRankPlayer().getRank("prestiges"); // Not sure how you want to represent this: - Material materialHas = Material.getMaterial(Objects.requireNonNull(guiConfig.getString("Options.Ranks.Item_gotten_rank"))); - Material materialHasNot = Material.getMaterial(Objects.requireNonNull(guiConfig.getString("Options.Ranks.Item_not_gotten_rank"))); + Material materialHas = Material.getMaterial(guiConfig.getString("Options.Ranks.Item_gotten_rank")); + Material materialHasNot = Material.getMaterial(guiConfig.getString("Options.Ranks.Item_not_gotten_rank")); boolean playerHasThisRank = true; int hackyCounterEnchant = 0; @@ -190,7 +189,7 @@ private void buttonsSetup(Optional ladder, int dimension, Inventory if (!(playerHasThisRank)){ if (hackyCounterEnchant <= 0) { hackyCounterEnchant++; - if (Objects.requireNonNull(guiConfig.getString("Options.Ranks.Enchantment_effect_current_rank")).equalsIgnoreCase("true")) { + if (guiConfig.getString("Options.Ranks.Enchantment_effect_current_rank").equalsIgnoreCase("true")) { itemrank.addUnsafeEnchantment(Enchantment.LUCK, 1); } } @@ -205,8 +204,7 @@ private void buttonsSetup(Optional ladder, int dimension, Inventory messages.getString("Lore.ClickToRankup") ); - ItemStack rankupButton = createButton(Material.EMERALD_BLOCK, 1, rankupLore, SpigotPrison.format("&aPrestige")); + ItemStack rankupButton = createButton(XMaterial.EMERALD_BLOCK.parseItem(), rankupLore, SpigotPrison.format("&aPrestige")); inv.setItem(dimension - 5, rankupButton); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index 06c947a7a..0ed784087 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Server; @@ -23,7 +24,6 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -130,7 +130,7 @@ public void open() { // Get many parameters RankLadder ladderData = ladder.get(); Rank rank = ladderData.getLowestRank().get(); - Rank playerRank = getRankPlayer().getRank( ladderData ).orElse( null ); + Rank playerRank = getRankPlayer().getRank(guiConfig.getString("Options.Ranks.Ladder")); // Call the whole GUI and build it if (guiBuilder(dimension, inv, rank, playerRank)) return; @@ -194,7 +194,7 @@ private void buttonsSetup(int dimension, Inventory inv, Rank rank, Rank playerRa messages.getString("Lore.ClickToRankup") ); - ItemStack rankupButton = createButton(Material.EMERALD_BLOCK, 1, rankupLore, SpigotPrison.format(messages.getString("Lore.Rankup"))); + ItemStack rankupButton = createButton(XMaterial.EMERALD_BLOCK.parseItem(), rankupLore, SpigotPrison.format(messages.getString("Lore.Rankup"))); inv.setItem(dimension - 5, rankupButton); } } \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java index 0fc26cefa..a2b16b3e1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java @@ -9,7 +9,6 @@ import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -95,9 +94,9 @@ private void buttonsSetup(Inventory inv) { // Create the button ItemStack closeGUI = createButton(XMaterial.RED_STAINED_GLASS_PANE.parseItem(), closeGUILore, SpigotPrison.format("&c" + "Close")); - ItemStack rankupCommands = createButton(commandMinecart, 1, rankupCommandsLore, SpigotPrison.format("&3" + "RankupCommands" + " " + rank.name)); - ItemStack rankPrice = createButton(Material.GOLD_NUGGET, 1, editPriceLore, SpigotPrison.format("&3" + "RankPrice" + " " + rank.name)); - ItemStack rankTag = createButton(Material.NAME_TAG, 1, editTagLore, SpigotPrison.format("&3" + "RankTag" + " " + rank.name)); + ItemStack rankupCommands = createButton(XMaterial.matchXMaterial(commandMinecart).parseItem(), rankupCommandsLore, SpigotPrison.format("&3" + "RankupCommands" + " " + rank.name)); + ItemStack rankPrice = createButton(XMaterial.GOLD_NUGGET.parseItem(), editPriceLore, SpigotPrison.format("&3" + "RankPrice" + " " + rank.name)); + ItemStack rankTag = createButton(XMaterial.NAME_TAG.parseItem(), editTagLore, SpigotPrison.format("&3" + "RankTag" + " " + rank.name)); // Set the position and add it to the inventory inv.setItem(10, rankupCommands); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java index d30e6b08a..3697f652f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.gui.rank; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.Configuration; @@ -7,7 +8,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -73,34 +73,39 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToIncrease") ); + Material decreaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack decreaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); + // Decrease button - ItemStack decreaseOf1 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 1" )); + ItemStack decreaseOf1 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 1" )); inv.setItem(1, decreaseOf1); - ItemStack decreaseOf5 = createButton(Material.REDSTONE_BLOCK, 10, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 10")); + ItemStack decreaseOf5 = createButton(new ItemStack(decreaseMat, 10), changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 10")); inv.setItem(10, decreaseOf5); - ItemStack decreaseOf10 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 100")); + ItemStack decreaseOf10 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 100")); inv.setItem(19, decreaseOf10); - ItemStack decreaseOf50 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 1000")); + ItemStack decreaseOf50 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 1000")); inv.setItem(28, decreaseOf50); - ItemStack decreaseOf100 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 10000")); + ItemStack decreaseOf100 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 10000")); inv.setItem(37, decreaseOf100); // Create a button and set the position - ItemStack confirmButton = createButton(Material.TRIPWIRE_HOOK, 1, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + rankName + " " + val)); + ItemStack confirmButton = createButton(XMaterial.TRIPWIRE_HOOK.parseItem(), confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + rankName + " " + val)); inv.setItem(22, confirmButton); + Material increaseMat = XMaterial.EMERALD_BLOCK.parseMaterial(); + ItemStack increaseStack = XMaterial.EMERALD_BLOCK.parseItem(); // Increase button - ItemStack increaseOf1 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 1" )); + ItemStack increaseOf1 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 1" )); inv.setItem(7, increaseOf1); - ItemStack increaseOf5 = createButton(Material.EMERALD_BLOCK, 10, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 10")); + ItemStack increaseOf5 = createButton(new ItemStack(increaseMat, 10), changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 10")); inv.setItem(16, increaseOf5); - ItemStack increaseOf10 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 100")); + ItemStack increaseOf10 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 100")); inv.setItem(25, increaseOf10); - ItemStack increaseOf50 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 1000")); + ItemStack increaseOf50 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 1000")); inv.setItem(34, increaseOf50); - ItemStack increaseOf100 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 10000")); + ItemStack increaseOf100 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " + 10000")); inv.setItem(43, increaseOf100); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java index baa32c80c..750af257b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java @@ -2,8 +2,8 @@ import java.util.List; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -11,7 +11,6 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; /** @@ -100,7 +99,7 @@ private void buttonsSetup(Inventory inv, String command) { commandsLore.add(SpigotPrison.format(messages.getString("Lore.Command") + command)); // Make the button with materials, amount, lore and name - itemCommand = createButton(Material.TRIPWIRE_HOOK, 1, commandsLore, SpigotPrison.format("&3" + rank.name + " " + command)); + itemCommand = createButton(XMaterial.TRIPWIRE_HOOK.parseItem(), commandsLore, SpigotPrison.format("&3" + rank.name + " " + command)); // Add the button to the inventory inv.addItem(itemCommand); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java index d13096799..78800bdbc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java @@ -4,9 +4,9 @@ import java.util.Optional; import java.util.stream.Collectors; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; @@ -17,7 +17,6 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.PrisonSetupGUI; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; @@ -139,7 +138,7 @@ private void buttonsSetup(Inventory inv, Optional rankOptional) { //getCommands(ranksLore, rank); // Make the button with materials, amount, lore and name - itemRank = createButton(Material.TRIPWIRE_HOOK, 1, ranksLore, SpigotPrison.format("&3" + rank.name)); + itemRank = createButton(XMaterial.TRIPWIRE_HOOK.parseItem(), ranksLore, SpigotPrison.format("&3" + rank.name)); // Add the button to the inventory inv.addItem(itemRank); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java index a6827a8b1..7415ea15f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java @@ -1,17 +1,15 @@ package tech.mcprison.prison.spigot.gui.sellall; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; +import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; -import java.util.Objects; import java.util.Set; @@ -60,7 +58,7 @@ private Inventory buttonsSetup() { } // Get the Items config section - Set items = Objects.requireNonNull(conf.getConfigurationSection("Items")).getKeys(false); + Set items = conf.getConfigurationSection("Items").getKeys(false); // Get the dimensions and if needed increases them int dimension = (int) Math.ceil(items.size() / 9D) * 9; @@ -70,7 +68,7 @@ private Inventory buttonsSetup() { return null; } - Inventory inv = Bukkit.createInventory(null, dimension, SpigotPrison.format("&3PrisonManager -> SellAll-Admin")); + Inventory inv = Bukkit.createInventory(null, dimension, SpigotPrison.format("&3Prison -> SellAll-Admin")); for (String key : items) { List itemsLore = createLore( @@ -78,7 +76,8 @@ private Inventory buttonsSetup() { "&aLeft-Click to edit value", "&3value: &a$" + conf.getString("Items." + key + ".ITEM_VALUE") ); - ItemStack item = createButton(Material.valueOf(conf.getString("Items." + key + ".ITEM_ID")), 1, itemsLore, SpigotPrison.format("&3" + conf.getString("Items." + key + ".ITEM_ID"))); + + ItemStack item = createButton(SpigotUtil.getItemStack(SpigotUtil.getXMaterial(conf.getString("Items." + key + ".ITEM_ID")), 1), itemsLore, SpigotPrison.format("&3" + conf.getString("Items." + key + ".ITEM_ID"))); inv.addItem(item); } return inv; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java index 9b38d65b5..e9c78a9db 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java @@ -1,17 +1,15 @@ package tech.mcprison.prison.spigot.gui.sellall; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; +import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; -import java.util.Objects; import java.util.Set; /** @@ -59,7 +57,7 @@ private Inventory buttonsSetup() { } // Get the Items config section - Set items = Objects.requireNonNull(conf.getConfigurationSection("Items")).getKeys(false); + Set items = conf.getConfigurationSection("Items").getKeys(false); // Get the dimensions and if needed increases them int dimension = (int) Math.ceil(items.size() / 9D) * 9; @@ -69,13 +67,14 @@ private Inventory buttonsSetup() { return null; } - inv = Bukkit.createInventory(null, dimension, SpigotPrison.format("&3PrisonManager -> SellAll-Player")); + inv = Bukkit.createInventory(null, dimension, SpigotPrison.format("&3Prison -> SellAll-Player")); for (String key : items) { List itemsLore = createLore( messages.getString("Lore.Value") + conf.getString("Items." + key + ".ITEM_VALUE") ); - ItemStack item = createButton(Material.valueOf(conf.getString("Items." + key + ".ITEM_ID")), 1, itemsLore, SpigotPrison.format("&3" + conf.getString("Items." + key + ".ITEM_ID"))); + + ItemStack item = createButton(SpigotUtil.getItemStack(SpigotUtil.getXMaterial(conf.getString("Items." + key + ".ITEM_ID")), 1), itemsLore, SpigotPrison.format("&3" + conf.getString("Items." + key + ".ITEM_ID"))); inv.addItem(item); } return inv; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java index 3b11735ef..299025c8c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.gui.sellall; +import com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.Configuration; @@ -7,7 +8,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.SpigotGUIComponents; import java.util.List; @@ -67,36 +67,39 @@ private void buttonsSetup(Inventory inv) { messages.getString("Lore.ClickToIncrease") ); + Material decreaseMat = XMaterial.REDSTONE_BLOCK.parseMaterial(); + ItemStack decreaseStack = XMaterial.REDSTONE_BLOCK.parseItem(); // Decrease button - ItemStack decreaseOf1 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 1" )); + ItemStack decreaseOf1 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 1" )); inv.setItem(1, decreaseOf1); - ItemStack decreaseOf5 = createButton(Material.REDSTONE_BLOCK, 10, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 10")); + ItemStack decreaseOf5 = createButton(new ItemStack(decreaseMat, 10), changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 10")); inv.setItem(10, decreaseOf5); - ItemStack decreaseOf10 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 100")); + ItemStack decreaseOf10 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 100")); inv.setItem(19, decreaseOf10); - ItemStack decreaseOf50 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 1000")); + ItemStack decreaseOf50 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 1000")); inv.setItem(28, decreaseOf50); - ItemStack decreaseOf100 = createButton(Material.REDSTONE_BLOCK, 1, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 10000")); + ItemStack decreaseOf100 = createButton(decreaseStack, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 10000")); inv.setItem(37, decreaseOf100); // Create a button and set the position - ItemStack confirmButton = createButton(Material.TRIPWIRE_HOOK, 1, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + itemID + " " + val)); + ItemStack confirmButton = createButton(XMaterial.TRIPWIRE_HOOK.parseItem(), confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + itemID + " " + val)); inv.setItem(22, confirmButton); + Material increaseMat = XMaterial.EMERALD_BLOCK.parseMaterial(); + ItemStack increaseStack = XMaterial.EMERALD_BLOCK.parseItem(); // Increase button - ItemStack increseOf1 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 1" )); + ItemStack increseOf1 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 1" )); inv.setItem(7, increseOf1); - ItemStack increaseOf5 = createButton(Material.EMERALD_BLOCK, 10, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 10")); + ItemStack increaseOf5 = createButton(new ItemStack(increaseMat, 10), changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 10")); inv.setItem(16, increaseOf5); - ItemStack increaseOf10 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 100")); + ItemStack increaseOf10 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 100")); inv.setItem(25, increaseOf10); - ItemStack increaseOf50 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 1000")); + ItemStack increaseOf50 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 1000")); inv.setItem(34, increaseOf50); - ItemStack increaseOf100 = createButton(Material.EMERALD_BLOCK, 1, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 10000")); + ItemStack increaseOf100 = createButton(increaseStack, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 10000")); inv.setItem(43, increaseOf100); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/PlaceHolderAPIIntegrationWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/PlaceHolderAPIIntegrationWrapper.java index feda452b6..b7cb55110 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/PlaceHolderAPIIntegrationWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/PlaceHolderAPIIntegrationWrapper.java @@ -7,7 +7,7 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; -import tech.mcprison.prison.integration.IntegrationManager; +import tech.mcprison.prison.integration.PlaceholderManager; public class PlaceHolderAPIIntegrationWrapper extends PlaceholderExpansion @@ -49,7 +49,7 @@ public String getAuthor(){ */ @Override public String getIdentifier(){ - return IntegrationManager.PRISON_PLACEHOLDER_PREFIX; + return PlaceholderManager.PRISON_PLACEHOLDER_PREFIX; } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/SpigotPlaceholders.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/SpigotPlaceholders.java index f7afb4aa9..a3f58ce06 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/SpigotPlaceholders.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/placeholder/SpigotPlaceholders.java @@ -8,9 +8,9 @@ import java.util.UUID; import tech.mcprison.prison.Prison; -import tech.mcprison.prison.integration.IntegrationManager.PlaceHolderFlags; -import tech.mcprison.prison.integration.IntegrationManager.PrisonPlaceHolders; import tech.mcprison.prison.integration.PlaceHolderKey; +import tech.mcprison.prison.integration.PlaceholderManager.PlaceHolderFlags; +import tech.mcprison.prison.integration.PlaceholderManager.PrisonPlaceHolders; import tech.mcprison.prison.integration.Placeholders; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.managers.MineManager; @@ -331,7 +331,7 @@ public void reloadPlaceholders() { Prison.get().getPlatform().reloadConfig(); - Prison.get().getIntegrationManager().reloadPlaceholderBarConfig(); + Prison.get().getPlaceholderManager().reloadPlaceholderBarConfig(); if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllCommands.java deleted file mode 100644 index 4ee49f444..000000000 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllCommands.java +++ /dev/null @@ -1,448 +0,0 @@ -package tech.mcprison.prison.spigot.sellall; - -import java.io.File; -import java.io.IOException; -import java.util.Objects; -import java.util.Set; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import tech.mcprison.prison.Prison; -import tech.mcprison.prison.PrisonAPI; -import tech.mcprison.prison.integration.EconomyIntegration; -import tech.mcprison.prison.modules.Module; -import tech.mcprison.prison.modules.ModuleManager; -import tech.mcprison.prison.ranks.PrisonRanks; -import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.game.SpigotPlayer; -import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminGUI; -import tech.mcprison.prison.spigot.gui.sellall.SellAllPlayerGUI; - -/** - * @author GABRYCA - */ -public class SellAllCommands implements CommandExecutor { - - // Check if the SellAll's enabled - public static boolean isEnabled() { - return Objects.requireNonNull(SpigotPrison.getInstance().getConfig().getString("sellall")).equalsIgnoreCase("true"); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - - // Check if the sellall feature's enabled once again - if (!isEnabled()){ - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR]&c Sorry but the SellAll Feature's disabled in the config.yml")); - return true; - } - - // Get the config and file - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(file); - - // If the args are 0 and the player's a prison admin or OP he'll get an help message, else will be like a shortcut of the /sellall sell command - if (args.length == 0){ - if (sender.hasPermission("prison.admin") || sender.isOp()) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Please use a command like /sellall sell-gui-add-delete-multiplier-setdefault")); - } else { - return sellallCommandSell(sender, conf); - } - return true; - } - - // Open the GUI - if (args[0].equalsIgnoreCase("gui")){ - - return sellallCommandGUI(sender, conf); - - // sellall sell - } else if (args[0].equalsIgnoreCase("sell")){ - - return sellallCommandSell(sender, conf); - - // sellall add - } else if (args[0].equalsIgnoreCase("add")){ - - return sellallCommandAdd(sender, args, file, conf); - - // sellall delete - } else if (args[0].equalsIgnoreCase("delete")){ - - return sellallCommandDelete(sender, args, file, conf); - - // sellall edit - } else if (args[0].equalsIgnoreCase("edit")){ - - return sellallCommandEdit(sender, args, file, conf, "] edited with success!"); - - // sellall multiplier add/delete - } else if (args[0].equalsIgnoreCase("multiplier")){ - - return sellAllMultipliers(sender, args, file, conf); - - // sellall setdefault will set default values for some default Prison servers blocks - } else if (args[0].equalsIgnoreCase("setdefault")){ - - values(sender); - - return true; - - } - - // sellall will give this error message - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] The first argument's not found, please try /sellall for a list of them!")); - - return true; - } - - private void valueSaver(String material, int value, CommandSender sender){ - Material materialM = Material.matchMaterial(material); - if (materialM == null){ - return; - } else { - material = materialM.name(); - } - Bukkit.dispatchCommand(sender, "sellall add " + material + " " + value); - } - - private void values(CommandSender sender) { - valueSaver("COBBLESTONE", 50, sender); - valueSaver("STONE", 50, sender); - valueSaver("COAL",50, sender); - valueSaver("COAL_BLOCK", 450, sender); - valueSaver("IRON_INGOT",75, sender); - valueSaver("IRON_BLOCK",600, sender); - valueSaver("REDSTONE", 101, sender); - valueSaver("REDSTONE_BLOCK", 909, sender); - valueSaver("GOLD_INGOT", 122, sender); - valueSaver("GOLD_BLOCK", 1100, sender); - valueSaver("DIAMOND", 200, sender); - valueSaver("DIAMOND_BLOCK", 1800, sender); - valueSaver("EMERALD", 300, sender); - valueSaver("EMERALD_BLOCK", 2700, sender); - valueSaver("LAPIS_LAZULI", 70, sender); - valueSaver("LAPIS_BLOCK", 630, sender); - } - - - - private boolean sellAllMultipliers(CommandSender sender, String[] args, File file, FileConfiguration conf) { - if (!(Objects.requireNonNull(conf.getString("Options.Multiplier_Enabled")).equalsIgnoreCase("true"))){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cMultipliers are disabled in the SellAll config!")); - return true; - } - - if (args.length < 3){ - sender.sendMessage(SpigotPrison.format("&c[PRISON WARN] &cWrong format, please use /sellall multiplier add/delete ")); - return true; - } - - if (Objects.requireNonNull(conf.getString("Options.Multiplier_Command_Permission_Enabled")).equalsIgnoreCase("true")){ - if (!(sender.hasPermission(Objects.requireNonNull(conf.getString("Options.Multiplier_Command_Permission"))))){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cSorry, but you don't have the permission [" + conf.getString("Options.Multiplier_Command_Permission") + "]")); - return true; - } - } - - if (args[1].equalsIgnoreCase("add")) { - // Add check if the Prestige is present - // Add to the SellAllCommandSell the check for Player prestige, if prestiges are enabled and if player have a prestige or use default, also if there're multipliers for that prestige or use default - - ModuleManager modMan = Prison.get().getModuleManager(); - Module module = modMan == null ? null : modMan.getModule(PrisonRanks.MODULE_NAME).orElse(null); - - PrisonRanks rankPlugin = (PrisonRanks) module; - if (rankPlugin == null) { - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR] &cThe Ranks module's disabled or not found!")); - return true; - } - - boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").isPresent(); - - if (!isPrestigeLadder) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cCan't find a -prestiges- ladder, they might be disabled in the config.yml.")); - return true; - } - - boolean isARank = rankPlugin.getRankManager().getRank(args[1]) != null; - - if (!isARank) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cCan't find the Prestige/Rank: " + args[2])); - return true; - } - - boolean isInPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").get().containsRank(rankPlugin.getRankManager().getRank(args[1]).id); - - if (!isInPrestigeLadder) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cThe -prestiges- ladder doesn't contains the Rank: " + args[2])); - return true; - } - - double multiplier; - try { - multiplier = Double.parseDouble(args[3]); - } catch (NumberFormatException ex) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry but the multiplier isn't a number [/sellall multiplier add " + args[2] + " Here-> " + args[2] + " <-")); - return true; - } - - conf.set("Multiplier." + args[2] + ".PRESTIGE_NAME", args[2]); - conf.set("Multiplier." + args[2] + ".MULTIPLIER", multiplier); - try { - conf.save(file); - } catch (IOException e) { - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR] &cSorry, the config didn't save with success!")); - return true; - } - - sender.sendMessage(SpigotPrison.format("&3[PRISON] &aMultiplier got added or edited with success!")); - - return true; - } else if (args[1].equalsIgnoreCase("delete")){ - - if (args.length != 3){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cPlease use a format like /sellall multiplier delete ")); - return true; - } - - if (conf.getConfigurationSection("Multiplier." + args[2]) == null){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cCan't find the Multiplier of the prestige " + args[2] + " in the sellallconfig.yml")); - return true; - } - - conf.set("Multiplier." + args[2], null); - try { - conf.save(file); - } catch (IOException e) { - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR] &cSorry, the config didn't save with success!")); - return true; - } - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &aMultiplier deleted with success!")); - - return true; - } - - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN] &cThe format's wrong, try again /sellall for info.")); - return true; - } - - - - private boolean sellallCommandEdit(CommandSender sender, String[] args, File file, FileConfiguration conf, String s) { - - if (Objects.requireNonNull(conf.getString("Options.Add_Permission_Enabled")).equalsIgnoreCase("true")) { - if (!sender.hasPermission("Options.Add_Permission")) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry, but you're missing the permission [" + conf.getString("Options.Add_Permission") + "]")); - return true; - } - } - - if (args.length < 2) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Please add an ITEM_ID [example: /sellall add COAL_ORE ]")); - return true; - } - if (args.length < 3) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Please add a price or value for the item [example: /sellall add COAL_ORE 100]")); - return true; - } - if (Material.getMaterial(args[1]) == null) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry but the ITEM_ID's wrong, please check it [/sellall " + args[0] + " Here-> " + args[1] + " <- " + args[2] + "]")); - return true; - } - - double value; - try { - value = Double.parseDouble(args[2]); - } catch (NumberFormatException ex) { - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry but the value isn't a number [/sellall " + args[0] + " " + args[1] + " Here-> " + args[2] + " <-]")); - return true; - } - - conf.set("Items." + args[1] + ".ITEM_ID", args[1]); - conf.set("Items." + args[1] + ".ITEM_VALUE", value); - try { - conf.save(file); - } catch (IOException e) { - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR]&c Sorry, an error occurred while saving the config")); - e.printStackTrace(); - } - - sender.sendMessage(SpigotPrison.format("&3[PRISON]&a ITEM [" + args[1] + s)); - - return true; - } - - - - private boolean sellallCommandDelete(CommandSender sender, String[] args, File file, FileConfiguration conf) { - if (Objects.requireNonNull(conf.getString("Options.Delete_Permission_Enabled")).equalsIgnoreCase("true")){ - if (!sender.hasPermission("Options.Delete_Permission")){ - return true; - } - } - - if (args.length < 2){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Please add an ITEM_ID [example: /sellall delete COAL_ORE]")); - return true; - } - - if (conf.getConfigurationSection("Items." + args[1]) == null){ - sender.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c " + args[1] + " not found in the config or got already deleted")); - return true; - } - - conf.set("Items." + args[1] + ".ITEM_ID", null); - conf.set("Items." + args[1] + ".ITEM_VALUE", null); - conf.set("Items." + args[1], null); - try { - conf.save(file); - } catch (IOException e) { - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR]&c Sorry, an error occurred while saving the config")); - e.printStackTrace(); - } - - sender.sendMessage(SpigotPrison.format("&3[PRISON]&a " + args[1] + " Deleted with success!")); - return true; - } - - - - // Essentially an edited shortcut - private boolean sellallCommandAdd(CommandSender sender, String[] args, File file, FileConfiguration conf) { - return sellallCommandEdit(sender, args, file, conf, "] added with success!"); - } - - - - private boolean sellallCommandSell(CommandSender sender, FileConfiguration conf) { - - if (!(sender instanceof Player)){ - sender.sendMessage(SpigotPrison.format("&3[PRISON ERROR]&c You aren't a player")); - return true; - } - - Player p = (Player) sender; - - if (Objects.requireNonNull(conf.getString("Options.Sell_Permission_Enabled")).equalsIgnoreCase("true")){ - if (!p.hasPermission("Options.Sell_Permission")){ - p.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry, but you're missing the permission [" + conf.getString("Options.Sell_Permission") + "]")); - return true; - } - } - - if (!(conf.getConfigurationSection("Items.") == null)){ - - // Get the Items config section - Set items = Objects.requireNonNull(conf.getConfigurationSection("Items")).getKeys(false); - - double moneyToGive = 0; - for (String key : items) { - double amount = 0; - while (p.getInventory().contains(Material.valueOf(conf.getString("Items." + key + ".ITEM_ID")))){ - p.getInventory().removeItem(new ItemStack(Material.valueOf(conf.getString("Items." + key + ".ITEM_ID")),1)); - amount++; - } - moneyToGive = moneyToGive + (Double.parseDouble(Objects.requireNonNull(conf.getString("Items." + key + ".ITEM_VALUE"))) * amount); - } - - // Get Spigot Player - SpigotPlayer sPlayer = new SpigotPlayer(p); - - ModuleManager modMan = Prison.get().getModuleManager(); - Module module = modMan == null ? null : modMan.getModule( PrisonRanks.MODULE_NAME ).orElse( null ); - - PrisonRanks rankPlugin = (PrisonRanks) module; - - if (Objects.requireNonNull(conf.getString("Options.Multiplier_Enabled")).equalsIgnoreCase("true")) { - - boolean hasPlayerPrestige = false; - double multiplier = Double.parseDouble(Objects.requireNonNull(conf.getString("Options.Multiplier_Default"))); - - if (rankPlugin != null) { - if (rankPlugin.getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()).isPresent()) { - String playerRankName; - - try { - playerRankName = rankPlugin.getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()).get().getRank("prestiges").name; - } catch (NullPointerException ex){ - playerRankName = null; - } - - if (playerRankName != null) { - hasPlayerPrestige = true; - multiplier = Double.parseDouble(Objects.requireNonNull(conf.getString("Multiplier." + playerRankName + ".MULTIPLIER"))); - moneyToGive = moneyToGive * multiplier; - } - } - } - - if (!hasPlayerPrestige) { - moneyToGive = moneyToGive * multiplier; - } - } - - // Get economy - EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); - - // Add balance - economy.addBalance(sPlayer, moneyToGive); - if (moneyToGive<0.001){ - sender.sendMessage(SpigotPrison.format("&3[PRISON]&c You have nothing to sell!")); - } else { - sender.sendMessage(SpigotPrison.format("&3[PRISON]&a You got $" + moneyToGive)); - } - } - - return true; - } - - - - private boolean sellallCommandGUI(CommandSender sender, FileConfiguration conf) { - - if (!(sender instanceof Player)){ - sender.sendMessage(SpigotPrison.format("&c[PRISON ERROR] You aren't a player")); - return true; - } - - Player p = (Player) sender; - - if (!Objects.requireNonNull(conf.getString("Options.GUI_Enabled")).equalsIgnoreCase("true")){ - if (p.isOp() || p.hasPermission("prison.admin")) { - sender.sendMessage(SpigotPrison.format("&c[PRISON ERROR] Sorry but the GUI's disabled in the SellAllConfig.yml")); - return true; - } - } - - if (Objects.requireNonNull(conf.getString("Options.GUI_Permission_Enabled")).equalsIgnoreCase("true")){ - if (!p.hasPermission(Objects.requireNonNull(conf.getString("Options.GUI_Permission")))){ - p.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry, but you're missing the permission [" + conf.getString("Options.GUI_Permission") + "]")); - return true; - } else if (Objects.requireNonNull(conf.getString("Options.Player_GUI_Enabled")).equalsIgnoreCase("true")){ - if (Objects.requireNonNull(conf.getString("Options.Player_GUI_Permission_Enabled")).equalsIgnoreCase("true")) { - if (!p.hasPermission(Objects.requireNonNull(conf.getString("Options.Player_GUI_Permission")))){ - p.sendMessage(SpigotPrison.format("&3[PRISON WARN]&c Sorry, but you're missing the permission [" + conf.getString("Options.Player_GUI_Permission") + "]")); - return true; - } - } - SellAllPlayerGUI gui = new SellAllPlayerGUI(p); - gui.open(); - return true; - } - } - - SellAllAdminGUI gui = new SellAllAdminGUI(p); - gui.open(); - - return true; - } -} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java index 03bc8df3d..2afd595ee 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java @@ -80,9 +80,9 @@ public BluesSemanticVersionData( String semVerStr ) { Pattern r = Pattern.compile(patternNamed); // Pattern r = Pattern.compile(pattern); - Matcher m = r.matcher(semVerStr); + Matcher m = ( semVerStr == null ? null : r.matcher(semVerStr) ); - this.valid = m.find(); + this.valid = ( semVerStr == null ? false : m.find() ); if ( isValid() ) { this.major = parseInt(m, GroupNames.major); @@ -135,16 +135,18 @@ private Integer parseInt( Matcher m, GroupNames groupName ) { Integer result = null; - String grp = parseString(m, groupName); - if ( grp != null ) { - - try { - result = Integer.parseInt( grp ); - } - catch ( NumberFormatException e ) { - // Should be an integer.... let the null be returned, record in messages: - getMessages().add( "### BluesSemanticVersionData.parseInt :: group " + groupName.name() + " = " + - grp + " ### Error Parsing int value ### " ); + if ( m != null ) { + String grp = parseString(m, groupName); + if ( grp != null ) { + + try { + result = Integer.parseInt( grp ); + } + catch ( NumberFormatException e ) { + // Should be an integer.... let the null be returned, record in messages: + getMessages().add( "### BluesSemanticVersionData.parseInt :: group " + groupName.name() + " = " + + grp + " ### Error Parsing int value ### " ); + } } } @@ -164,14 +166,17 @@ private Integer parseInt( Matcher m, GroupNames groupName ) private String parseString( Matcher m, GroupNames groupName ) { String result = null; - try { - result = m.group( groupName.name() ); - } - catch ( IllegalArgumentException e ) { - getMessages().add( "### BluesSemanticVersionData.parseString :: group " + groupName.name() + " = ?? " + - " ### Error Capture Group Doesn't Exist in the Regular Expression ### " ); + if ( m != null ) { + try { + result = m.group( groupName.name() ); + } + catch ( IllegalArgumentException e ) { + getMessages().add( "### BluesSemanticVersionData.parseString :: group " + groupName.name() + " = ?? " + + " ### Error Capture Group Doesn't Exist in the Regular Expression ### " ); + } } + return result; } diff --git a/prison-spigot/src/main/resources/config.yml b/prison-spigot/src/main/resources/config.yml index b5c504266..a9fd03345 100644 --- a/prison-spigot/src/main/resources/config.yml +++ b/prison-spigot/src/main/resources/config.yml @@ -36,8 +36,13 @@ show-alerts: true # NEW: Prison now has prestiges! # https://github.com/PrisonTeam/Prison/blob/bleeding/docs/prison_docs_107_setting_up_pestiges.md +# Note: "prestiges: true" is deprecated and will be removed in the future. prestiges: true +prestige: + enabled: true + resetMoney: true + # NEW: This enables new physics to be applied when jumpping on slime blocks. # When holding different items, like some block types or picks, the player can # jump even higher to heights of 40 to 60+ blocks. @@ -77,12 +82,19 @@ prestige-confirm-gui: true # New feature so setting to false since it will override other shop plugins. sellall: false +# NEW: SellAll sign +# New sellall feature which enable a sign with the name of [SellAll] to execute the command /sellall sell of Prison +# To make a sign, give yourself the permission prison.admin and then add as the first line of a sign the tag [SellAll] +sellall-sign: false +sellall-sign-notify: false +sellall-sign-visible-tag: "&7[&3SellAll&7]" + # NEW: Broadcast rankups and demotions to the whole server, in all worlds. # If this value does not exist, or has a true value, it will be broadcasted. # Any other value besides true, or non-existant, will be treated as false. -broadcast-rankups: true +broadcast-rankups: false @@ -150,5 +162,12 @@ storageType: "json" # NEW: Non-functional. Coming soon! +# Prison mines reset gap is the number of milliseconds that are used to +# space out the mine resets when starting the server. This value should +# not be changed unless you understand what you are doing. This value +# is converted to ticks, so should use 50 millisecond increments. If too +# small of a value is used then it could produce a large amount of lag +# if more than one mine tries to reset at the same time, or close to each +# other. This may be changed to ticks in the near future. #prison-mines-reset-gap: 5000 diff --git a/prison-spigot/src/main/resources/plugin.yml b/prison-spigot/src/main/resources/plugin.yml index b510ff218..d28ad72e8 100644 --- a/prison-spigot/src/main/resources/plugin.yml +++ b/prison-spigot/src/main/resources/plugin.yml @@ -3,7 +3,7 @@ main: tech.mcprison.prison.spigot.SpigotPrison version: "${version}" description: Prison is an all-in-one plugin for the Minecraft prison game mode. website: https://prison.jar-mc.com -softdepend: [Essentials, Vault, LuckPerms, Multiverse-Core, Multiworld, MVdWPlaceholderAPI, PlaceholderAPI, GemsEconomy, TokenEnchant] +softdepend: [Essentials, Vault, LuckPerms, Multiverse-Core, Multiworld, MVdWPlaceholderAPI, PlaceholderAPI, GemsEconomy, TokenEnchant, CMI] # Older versions than 1.13 will ignore this, but this will allow 1.13 and up to use newer block types? api-version: 1.13 @@ -11,14 +11,6 @@ api-version: 1.13 # ====================================================== # New commands compatible only with spigot # ====================================================== -commands: - #prisonmanager: - #description: Call a fancy GUI where manage the ranks and mines - #usage: / gui - sellall: - description: SellAll Command and SubCommands - usage: / - permissions: