diff --git a/.gitignore b/.gitignore index d1cddf832..57cc6bdb7 100644 --- a/.gitignore +++ b/.gitignore @@ -102,7 +102,14 @@ local.properties *.war *.ear + +# Prison libs: .jar files are usally ignored, so must add these libraries: !/prison-spigot/lib/**/*.jar +!/prison-core/lib/**/*.jar + +# but exclude this directory: +prison-spigot/lib/old/ + # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* diff --git a/build.gradle b/build.gradle index 8e7504ecf..2e940621c 100644 --- a/build.gradle +++ b/build.gradle @@ -127,6 +127,11 @@ subprojects { includeGroup 'org.apache.commons' } } + + maven { + url "https://mvnrepository.com/artifact" + + } } diff --git a/docs/changelog_v3.2.x.md b/docs/changelog_v3.2.x.md index 35bcf3910..6067b2961 100644 --- a/docs/changelog_v3.2.x.md +++ b/docs/changelog_v3.2.x.md @@ -4,7 +4,7 @@ ## Build logs - **[v3.3.x - Current](changelog_v3.3.x.md)** - - [v3.2.0 through v3.3.0-alpha.14](prison_changelogs.md) + - [v3.2.0 through v3.3.0-alpha.16](prison_changelogs.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)   diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 837761593..0c3a4a436 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -4,7 +4,7 @@ ## Change logs - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** - - [v3.2.0 through v3.3.0-alpha.14](prison_changelogs.md) + - [v3.2.0 through v3.3.0-alpha.16](prison_changelogs.md) * [Known Issues - Open](knownissues_v3.2.x.md) * [Known Issues - Resolved](knownissues_v3.2.x_resolved.md) @@ -14,371 +14,560 @@ These change logs represent the work that has been going on within prison. -# 3.3.0-alpha.15 2023-07-07 +# 3.3.0-alpha.16 2023-11-18 +**v3.3.0-alpha.16 2023-11-18** -* **2023-07-07 v3.3.0-alpha.15 Released** +* Update change logs for v3.3.0-alpha.16 -* **This doc was failing to generate github docs due to issues with non utf-8 characters.** -Changed them to dashes. Not sure what caused these characters to become non-compliant. +* **Fixed an issue with ranks being disabled. It now skips over this processing when ranks are disabled.** -* **Update the known issues doc...** +* **Modules: Changed the way some of the module management is used to help prevent errors when a module is disabled.** +Suppress disabled modules from the placeholder list... only Ranks and Mines, which covers all of the placeholders. -* **Doc updates for the latest alpha.15 release.** -* **Added comments to the prison-spigot/build.gradle configs to add more descriptive comments.** -Checked the libraries and all are up to date. +* **Sellall: Standardize how sellall is being checked to see if it's enabled.** +There are still a few ways it can be improved, but this is a step in the right direction. +There was a problem with the older way things were being handled that was causing an NPE with the SpigotPlayer, which was brought to my attention by DinoFengz, but I noticed there were other problems that needed to also be addressed. -* **Setup the topN stats to be included in the /prison version information.** +* **Economy support for CoinsEngine: support has been initially added**, but it is unsure if it is working correctly. This request originated from pingu and they said it's not working, but has not provided any more information. Unsure how it's not working, or if they cannot use it the way they originally envisioned because sellall cannot support different currencies for different items within sellall. +Because of the lack of an API jar to be used, a new sub-project 'prison-misc' was created to be able to generate a pseudo-shell api for the CoinsEngine plugin. This pseduo api jar is used strictly to allow the successful compiling of the prison's economy hooks for CoinsEngine. +NOTE: I have not heard back from pingu to know if this is working. If you try to use this plugin and you have issues, please contact me on our discord support server. -* **Added the language files for the three new topN messages.** +* **Block Converters: Change the usage to Player instead of RankPlayer since if ranks are disabled then RankPlayer could not exist.** -* **Update the topN command to eliminate the use of the save file.** -All players are dynamically loaded by the refresh task. Stats have been added and are not a new option for the command. -To act as a form of debugging feature, the save of the topN data has been disconnected from the current process. +** 3.3.0-alpha.15h 2023-11-05** -* **Updated ItemsAdder from v3.2.5 to v3.5.0b** -because github's build was failing to find v3.2.5 online and was killing the prison build. +* **Player Cache: Put some of the player cache numbers in to the config.yml file so they can be fine tuned if desired.** +See the changes to config.yml for information to what the new setting controls. -* **Update topN Stats.** This is not the same as topNPlayers and this is not yet being used. -This tracks topN on blocks mined, tokens, and the player's ranks and balances. -The comparator was not correct and was fixed. +* **GUI: Add support for changing the gui item names for Ranks and Mines. Ranks can now set their material type too.** -* **MC 1.18 new world height support.** -Prison now supports the newer world heights as found in mc 1.18.x and newer. -The new range for Y is from -64 to 320. +* **Updated nbt-api and fixed a new issue that was introduced with mc 1.20.2.** -* **Bug fix: found that under a rare situation that it was trying to use an empty String with decimal formatting.** -This was found while testing some placeholders while players were offline. +* **Placeholder attribute time: add the time attribute to 4 more placeholders.** -* **I made a mistake when adding the new feature to skip player scans on startup.** -I added a new root perm in config.yml that started with `prison-ranks` when `ranks` already existed. Therefore, I changed the defaults in config.sys to fix this and changed the code to allow the old version of the config (the bad version) and the newer version. +* **Auto Sell: Bug fix for full inventory when auto sell is toggled off, which was incorrectly selling the player's inventory.** -* **Changes to the help for `/rankup` and `/prestige` commands to make it a little more clearer** as to what is expected with perms and to provide more details. -Added a new config setting to disable the need to use the prestige perm `ranks.rankup.presetiges` which may make it easier to get presetiges working on most servers. -Prestiges still requires the use of the `ranks.user` perm which is the same perm used for `/rankup`. +* **Prison Debug: Added support to target some debug logging to a specific player.** +When enabled, it will ignore all other players. Not all debug messages have been hooked up. More can be added upon request. +When debug mode is disabled, it will remove the debug player name. -* **Updated the PrisonJarReporter tool to include java versions 19, 20, and 21.** -Also fixed a bug in which if the version signature is not known, then it was returning a null. Now it returns an enum of type "JavaSE_UnknownVersion" which will prevent future errors. +* **Placeholders: Added support for a new placeholder attribute to better format time based placeholders.** +* **Placeholders: Added the ability to provide a shorted output of the command `/prison placeholders test` so it only shows the command header and the results.** +Use the '-s' flag as in: '/prison placeholders test -s' -* **2023-06-20: Version 3.3.0-alpha.14c released** +* **Placeholders: bug fix: If using the placeholder attribute for an off line player, it would cause an error when checking if the player was in a disabled world.** -* **Totally stupid change: github's compiler forgot how to use overloaded functions so it was trying to use the wrong one.** -Renaming the function should help it's anti-AI skill sets. +* **SellAll messages: Cleaned up some of the US EN messages related to the sellall command.** -* **Fixed the way prison was using the nbt-api.** -Now using the correct repo and the newer API functions. +* **Bug: sellall auto sell enabled messages reversed.** +The command to enable and disable the auto sell feature was reversed, so when turning off, it would report that it was just turned on. And on when it was turned off. -* **Trying to get nbt-api setup properly with shadowing.** It looks like it's correctly shadowed, but it's being improperly reported as not being shadowed. I have a conversation with the developer open to figure out what's going on with this issue. +**v3.3.0-alpha.15g 2023-10-03** -* **Update the item-nbt-api library to v2.11.3 from v2.11.2.** -Turned out the maven repo they actually use was not mavencentral.com, of which, has not yet pulled in the updated version. Using the correct repo now. +* **Player Economy Cache Delay: Add the ability to change the player economy cache delay. Default value is 3 seconds, or 60 ticks.** -* **Update libraries:** -Update bstats from v3.0.0 to v3.0.2. -Update XSeries from v9.2.0 to v9.4.0. -Update vaultAPI from v1.7.0 to v1.7.1. +* **Prison version: Improve the content of the auto features details.** -* **Changed config.yml to be able to bypass the add new player at prison startup.** This would be more related to servers that already have a large player base when they switch to this plugin. -NOTE: It's not possible to fully test all conditions where a player object may be null. Use at your own risk if you do not allow prison to scan for new players at startup. If an error is found, please contact support ASAP in our discord server so we can get it fixed for you. +* **Placeholders: Added the ability to specify a player name in all placeholder attributes.** +This can allow the use of placeholders that are player centric in plugins that cannot support player based placeholder requests. -2023-06-13 : -* **Update how the player objects are written when dirty.** There were some situations where the RankPlayer object would be written to the file system 2 or 3 times for one change. -The logic of how things are nested remains the same (to minimize breakage of the code), but the RankPlayer is not utilizing a dirty flag internally so if it's saved once, it skip the other attempts to save without changes. +* **Autosell: Setup the SpigotPlayer object to support functions to identify if the player has autosell enabled. This is used in a couple of places to eliminate redundancy.** +Fixes a problem with the block break event not also checking to see if the player has toggled their autosell status for the forced sell after the event is processed, and also the delayed sell. -* **Simple example illustrating the weakness of doubles with large values.** +* **Cleanup the '/ranks list' to add mines and better format the name, tag, and cost.** +Also removed rankId which is not important anymore. -* **Update nbt api to v2.11.2 from v2.11.1** +* **Auto features: change a few of the new line breaks so there are fewer.** -* **Added ExaltedEconomy to the soft depends so prison will wait until it is loaded before trying to startup.** 2023-05-24 +* **Changed the default color code from `&9` (dark blue) to `&b` (light blue) for debug logging since the dark blue could be difficult to see on some consoles. -* **Fixed an issue that if the prison config files are manually modified and as a result, the block events cannot be parsed, this fix prevents a null value being inserted in to the loaded block events.** -For example, a trailing comma would produce a null block event because the parser that prison uses will read the comma, then with nothing else following it, it injects a null in to the collection of raw data for the block events. Then when that raw data is parsed, it passed along that null as a valid block event. The fix, prevents any of the nulls from being added to the active block events. +**v3.3.0-alpha.15f 2023-09-24** -* **A sellall gui message that was supposed to say that the gui was not enabled only said sellall was not enabled. Added a new message to clearly state it's the gui that is not enabled.** +* **TopNPlayer: Task could not startup if ranks are enabled but there are no default ranks.** +Log a message in the console that the task cannot start because ranks are enabled and there are no ranks. +Request that Ranks module is disabled, or add default ranks and then restart the server. -* **Get part of sellall to work if ranks are disabled. The command /sellall sell works, but the other sellall commands need to be tested and fixed.** +* **Prison Support: Added a more secure method and server (privatebin) for submitting server information under prison support submit commands.** +Can now control some of the settings that are used, including password, in the config.yml file. +May need to refresh config.ymml to see now settings. -* **Bug fix: bstats and topn was using the wrong function to check to see if ranks were enabled.** +* **MineBombs: validate all mine bombs upon server startup to validate the sound effects, visual effects, and shape based upon the version of spigot that they are running.** +This mostly is to clean up the default mine bombs where they have sound and visual effects for versions of spigot so something will happen. This removes the invalid ones for the version so there are less errors at run time. -* **Fixed an issue when cannot get a player from bukkit** +* **MineBombs: Add support for customModelData for the item used for the bomb.** +This will only work on spigot version 1.14.x and higher. -* **AutoFeatures bug fix: If normal drops is enabled (no auto pickup), and sellall was disabled, then normal drops were being disabled.** -The location of checking for if sellall was active was in the wrong location, which was preventing prison from actually dropping the blocks for the player. +* **Prison compatibility: Added support for block metadata customModelData.** +This is only compatible with spigot 1.14.x and higher. -* **Fixed an issue with prison utils potions where if the player was null, then it was throwing an NPE. ** +* **Ranks Ladder resetRankCost: Added a new parameter to provide an exponent which is used as a Math.pow() function over the base rank cost calculations.** +This can help increase the rank costs for higher ranks. +Default value is 1.0 so it does not apply unless it is specifically changed. + -* **AutoFeatures: Rev Enchants JackHammerEvent: Bug fix: The jackhammer event was not returning a list of all of the blocks involved in the event, which could be excluding hundreds if not more than 1000 blocks.** -The fix, uses the two points to calculate which blocks to include, and then include them through that cuboid instead of getting a list of blocks from the event. +* **Update the Double vs BigDecimal example. Increased from 25 to 35 iterations, and expanded all columns to adjust for the wider output.** -* **BugFix: Fixes an issue with sellall where it is trying to sell an invalid ItemStack.** -As a result, the sellall pays the player for the itemstack but the itemstack is not removed. This fixes it by not trying to sell the questionable itemstacks. +* **Block Converters: event triggers: More work. Got it working to the point that it's ready for production.** +The way it is right now, any block that is in an event trigger, will be excluded from all explosions. They will remain unbroken in the mine. +The players can then break them directly to trigger the events. Eventually I may allow processing within an explosion event, but right now it's not making sense to process 100+ triggers all at one time for huge explosions... the other plugin that's being "fired" may cause lag trying to process that many at one time. -* **AutoFeatures: Add a bukkit drops multiplier which is applied to the bukkit drops before the fortune calculations are performed.** -This can be used to reduce the total number of drops if a value less than 1.0 is used. A value of 1.0 does nothing. A value greater than one will increase the bukkit drops. All values are floored and are integers. +* **BlockConverters eventTriggers: Fixed the handling of event trigger blocks so they can be ignored within an explosion event. Now works.** +Still have to process the event trigger blocks in explosions for when they need to be triggered. -**Update to v3.3.0-alpha.14b** 2023-02-26 +* **Sellall command: '/sellall set delay' - fixed the description which had a typo in the description.** -* **AutoFeatures bug fix: If global fortune multiplier is set to a value lower than 1, then there is a risk of zero drops; this prevents zero drops and returns a drop of one.** +* **SpigotPlayer: fixed a problem where the object was expected to be comparable.** -* **Fixed an issue with the initial event check for events that will break multiple blocks.** -The issue is that the initial check will ignore the event if the primary block is air. The issue is that since the events are fired based upon the BlockBreakEvent then the odds of the primary block is AIR is very high. So for those events, the primary block should not be checked for AIR to be bypassed. This fix allows things like explosions to work. +* **BlockConverters eventTriggers: Add the support for explosion events to all of the explosion event handlers.** -**Update to v3.3.0-alpha.14a** 2023-02-25 +* **BlockConverters EventTriggers: Setup the next phase of handling where blocks in explosions can be ignored.** -* **Enhanced the debug reporting for fortune calculations and fixed a few uses of the newer fortune settings, some of which were used in the wrong locations.** +* **BlockConverters EventTriggers - setup the PrisonMinesBlockBreakEvent to allow an event to identify if the primary block must be forcefully removed**, which is only used right now with event triggers, and would remove the block when handling a MONITOR event, which normally does not remove any blocks. -* **Updated the formatting on the prison's mine wand for debug reporting of which blocks are clicked on.** -The information has been cleaned up to be easier to read and follow. It's now being logged in the console too so the details can more easily be reported back for troubleshooting. +* **BlockConverters EventTriggers: Setup more controls within the settings of a blockEvent.** +Setup the ability to control processing of drops: if disabled, it will treat the block event as a MONITOR. This allows the block to be counted correctly. +Setup the ability to ignore the block type within all explosions, so each block would have to be broken individually. +Setup the ability to remove the block without dropping anything since another plugin would have already processed the block, so nothing would remain to be done with it. -* **Updated the auto features config file to include the ACCESS priorities in the list of priorities so its better understood what the real options are.** +* **Mines block edit - Found a problem where if you are trying to edit a block and the name does not match, it was causing an error.** Now reports that the block name is invalid. -* **Enhanced some of the auto features logging related to fortune, silk touch, and event and drop canceling to eliminate ambiguity and provide more specific details.** +* **Block Converters - Event Triggers - Had issues with block names not matching, so using all lower case. When using an event trigger it now logs the debug info to the console.** +This will need more work, such as block removal and logging as if it were a MONITOR priority. +At this point, we are testing to confirm that the event is actually being triggered. So far it looks like it is working as intended. -* **Fixed an issue with player counts being doubled. Counts should no longer be done within the auto pickup or the normal drops... it's being handled at a higher level for consistency with other priorities.** +* **Block Converters: Start to hook up block converters to auto features.** +Changed how block converters were structured to get them to work with the prison environment. +Hooked up the Block Converter Event Trigger to the bukkit BlockBreakEvent. Explosions are not yet covered, will add support for them if this appears to work. -* **Added a fortune multiplier that is applied to all fortune calculations, which allows for increasing or decreasing the results of the fortune.** +* **Update docs and some command descriptions to make them a little more clearer as to what they do.** -* **French support added by Maxcension. Thanks Maxcension!** +* **sellall multipliers list: Added 2 options to control the number of columns displayed with 'cols=7' and also only show multipliers for a single ladder if that ladder name is provided in the options.** -* **Move the check for access to the OnBlockBreakMines.ignoreMinesBlockBreakEvent so it is logged with the other conditions.** +* **sellall multiplier list: Now applies a sort order to the ranks, grouping by ladders.** It groups by ladders, and then lists the ranks in rank order, within each ladder. -* **Setup minecraft statistics so prison can report block mining through a new setting within the auto features.** +* **sellall multiplier addLadder: added more comments to the command's help, and added defaults to the parameters.** -* **Enable silk touch enchantment by dropping the actual blocks that are being broke.** -If alt fortune is being used, then fortune will apply to these silked drops. -If players place silked blocks back in the mines (fi that feature is enabled), prison will ignore those blocks and won't break them... it will let bukkit or another plugin deal with them, but it will not apply any fortune to them. +* **SellAll multipliers: Increased the number of columns for the listing to 8 columns instead of 5.** May need to expand it even more so if there are thousands of ranks, it can be better managed. +New command: `/sellall multiplier deleteLadder` deletes all multipliers for that ladder. +New command: `/sellall multiplier addLadder` adds multipliers for all ranks on the ladder. -* **Bug Fix autosell: was trying to access autosell when it was disabled.** +* **Ranks Auto Configure: Fixed message format when options are not valid so it's better understood what's wrong with the command.** +The parameter names are case sensitive, but added a fallback mapping to lowercase so there is a higher chance of matching the correct commands. +Had to move the location of the 'prestigeMulti=' parameter to be evaluated before 'multi=' parameter since it was taking over the `prestigeMulti=` parameter. -* **Update google gson (json IO tool) from v2.8.6 to v2.10.1** +* **Update the rank's getPosition() java docs to better clarify what it is.** -* **Update google guava from v19.0 to v31.1-jre. Guava is used for internal event listeners.** +* **Ladders: Added a new command to reset all rank costs for a given ladder: '/ranks ladder resetRankCosts help'** +This will allow a simple and easy change to all rank costs within a given ladder even if there are many ranks, such as the presetiges ladder which could have thousands of ranks. +These calculations are similar to how the `/ranks autoConfigure` will set them up. -* **Prison Debug Block Inspector: Expand and enhanced the prison tool to provide an inspection of the block break events.** -Added event block details and drops being canceled for each listener. Reformatted to make it easier to read. +* **Prison logging: When line breaks are applied in log messages, it will no long include the prison template prefix with the message to reduce the clutter and make it easier to read multi-lined content.** +The line break placeholder is '{br}', similar to the html element BR. -* **Remove the optional from getModule functions since java 17.0.6 was failing.** -Not sure if it's an actual java issue, or a problem caused by another plugin, or etc... this works well with java 17.0.2. -* **Minor improvements to the EventResultsReasons to show a success and more detailed debug logging.** +**v3.3.0-alpha.15e 2023-09-03** +* **Prison messages: Expanded the use of prison message line breaks, `{br}` in both console messages and sending messages to player.** +Auto Features: Added line breaks to the existing block break debug info since it's very long and difficult to read. -* **Relocate the ACCESS failure which will trigger a TP to an accessible mine...** -this is relocated because it's not an event, but a behavior triggered by an event condition. +* **Mine wand debug info: Slightly alter the printing of the details to make it easier to read.** -* **Setup a temp test to test ItemsAdder.** -* **AutoFeatures: new feature to process MONITOR and BLOCKEVENTS only if the block is AIR.** -The reason for this is that if we are monitoring a blockbreak event, then we can assume that the block should be AIR. This setting is important for enchantment plugins handling the block break events, since a non-AIR value would indicate that the player was not successful in breaking the block. -Added more detailed debugging logging if the event is fast-failed or under normal conditions. +* **AutoFeatures and prison version: I have no idea why I added an auto features reload when doing prison version. Removed.** +Best guess at this moment is that it was to test something. -* **Change the block break priority BLOCKEVENTS to MONITOR. Updated the docs too.** +* **Prison GUI: When disabled through the config.yml 'prison-gui-enabled: false' there were still some commands that were being registered with the '/gui' root.** +As a result, prison was taking over the use of the command '/gui' that was trying to be used by other plugins. +This fix tries to isolate the GUI commands from backpacks, prestiges, and sellall, to make sure they cannot be registered if GUI is disabled. +Had to create new classes to allow the isolation when registering the commands. -* **Add new autoFeature setting to allow non-prison placed blocks to be handled by bukkit: ifBlockIsAlreadyCountedThenCancelEvent: true. (default setting).** -Prison was canceling the event if it found a block placed in the mine that it did not place during a mine reset. This would allow players to place blocks and then remove them if they have the worldguard perms to do block breaks. -These blocks are not tracked in prison and are not handled. Prison just ignores them. +* **AutoManager: percent gradient fortune: Changed the calculations to use doubles instead of integers.** -* **Fixed the gui config which it needed to load after loading ranks and mines. So it's initialized a second time in the startup process.** +* **Slime-fun: Moved a lot of the settings for it to the config.yml file instead of hard coding them.** +Now the messages can be turned off, and the boosters can now be added to, and changed. -* **Gui Player Mine config settings: Added `Options.Mines.MaterialType.NoMineAccess` which defaults to REDSTONE_BLOCK.** -If it does not exist in a player's GuiConfig.yml file, it will now be auto added. -Also if the `Options.Mines.MaterialType` block list of material types to use for each mine does not exist, it will auto add them, using the first block in the mine's block list. +* **Sellall: Fixed a bug with spigot 1.8.8 where bricks were not able to be sold correctly.** +The issue is with XBlock not correctly mapping brick and bricks to the correct bukkit 1.8 materials. It may be close, or accurate, but when converting to a bukkit item stack, it fails to map back to the same objects. +Sellall was not using the prison compatibility classes, and those classes for 1.8 had to be updated too. -* **Some adjustments to AutoFeatures and monitor priority... it was processing block events under some conditions.** +* **AutoFeatures: New option to use TokenEnchant to get the enchantment level through their API instead of using the bukkit functions to get the fortune.** -* **Mine BlockEvents: Enables the use of pipes in commands and messages now.** +* **AutoFeatures: Added a debug statement when player autosell has been toggled off by the player, since it may look as if autosell is not working correctly.** +Wrapped the notice in a WARNING color code so it stands out in the console with it being red. -* **MineBombs: Added a new field specifically for the item name for the bomb.** -The mine bombs now auto load upon startup and will auto update now if there is a change in mine data versions. +* **AutoFeatures: Updated the gradient fortune to fix a problem with not setting the bonus block counts correctly.** -* Changed the example world names in the config.yml file where Prison is disabled. Too many people were running in to the problem where they just happened to have those worlds, and that's where they were trying to use prison. So they were thinking Prison was not working instead of Prison being disable in those worlds because that's what was in the configs. +* **AutoManager: Added a new fortune type: percentGradient.** +This fortune calculation is an alternative to the extendedBukkit and altFortune calculations. +This fortune calculation applies a linear distribution based upon the player's tool's fortune level versus the maxfortuneLevel and the maxBonusBlocks. -**Prison v3.3.0-alpha.14 2023-01-23** +* **Added a `/mines top` command, alias `/mtop`, which will tp a player to the spawn location of the current mine they are in. ** +If they are not in a mine, then it will tp them to a mine tied to their current default rank. -The following are significant changes that are included in the alpha.14 release since the alpha.13 release was posted. +**v3.3.0-alpha.15d 2023-08-16** -* Support for RevEnchants +* **Mine reset time: Found a conflict with the setting '*disable*' being ignored.** +It's been fixed. -* Added more flexibility in supporting Prison Event Listener priorities for block break events so prison is better suited to support more enchantment plugins under more conditions. Added ACCESS, ACCESSBLOCKBREAKS, and ACCESSMONITOR to provide far more flexibility when prison is NOT managing the block breakage. +* **BlockBreak sync task: Found a possible cause of jitters, or visual appearance of lag.** +Basically, need to check the block to ensure it's not already AIR before setting it to AIR. This could happen if there is a heavy load on the server from other plugins, or from bukkit itself, and bukkit naturally breaks the block before prison's sync task can get to it. +Prison submits the sync task to run "next" in the future, but if there are other tasks trying to run, and if they cause a longer delay, then it can appear to be laggy. -* General improvements in how Auto Features manages the event listeners for all of the block break events. Includes some bug fixes and performance improvements too. +* **AutoFeatures: Expand the number of features being reported to bstats.** +Removed a duplicate comment in the autoFeatures config file. -* Preparing to support ItemsAdder... will be available in next alpha release.* +* **AutoFeatures: Add comment on autosell by perms so it's clear what setting are needed.** +Also added a setting of 'false', in addition to 'disable', which disables the permission based autosell. -* Prison Placeholders: Added a few more, fixed a few bugs, and improved documentation so its easier to understand how to use them. Added more features to the command `/prison placeholders stats`. The stats command can actually be used to troubleshoot issues with third-party plugins trying to use prison placeholders. +* **AutoFeatures XPrison event listener: Fixed a bug that was ignoring the first block in the exploded block list.** -* Top-n reports and placeholders: bug fixes and added a few more features. +* **AutoFeatures: Added the ability to force a delayed inventory sellall at the end of handling a bukkit BlockBreakEvent. This is in addition to the other instant sellall at the end of the bukkit BlockBreakEvent.** +This has the ability to set a delay in ticks before it is fired. +If a task was submitted for a player, then future tasks cannot be submitted for that player until the submitted sellall task was finished running. +This was added to help cover situations where third party plugins are trying to add additional bonus drops to the players, but after prison is done handling the events. -* Mine commands: refactor and improvements to some of the general mine commands. +* **AutoFeatures: Added the ability to force an inventory sellall at the end of handling a bukkit BlockBreakEvent.** +This was added to help cover situations where third party plugins are trying to add additional bonus drops to the players. -* Prison Placeholders: general bug fixes and performance improvements with the placeholder cache. +* **auto features: setup a sellall function on PrisonMinesBlockBreakEvent so it can be easier to utilize from other functions.** -* Prison's bstats: Expanded the reports that are being included. +* **AutoFeatures SellAll: Added the ability to disable the "nothing to sell" message without effecting the other settings.** -* Prison Command Handler: ability to lockout players from commands and tab-completes based upon perms. +* **auto features: Add the calculated autosell to the dropExtra function to force autosell if it should happen to have extra drops left over (it never should).** -* Mines GUI Bug fixes: fixed a few issues. +* **Auto Features: If autosell is enabled and there are any leftover blocks that was not sold, it will now generate an error message and if prison debug mode is turned off, then it will force the logging of the transaction.** +This forcing the logging can be turned off in the auto features configs. +Expanded the logging to change the color on some of the more important warnings and failures so they stand out. +Also reworked some of the log details to eliminate redundancy and clarify what's being logged. -* Issue with vault not working with essentials: Not able to access player's balances through vault and provided alternative paths to resolve this issue. +* **AutoFeatures: Added support for XPrison's enchantments... forgot to add the API jar which is used to just compile prison (not used on servers).** -* Prison support new feature: tracking command usage along with average run times: `/prison support cmdStats`. +* **Prison Placeholders: Added support to disable placeholders in disabled worlds.** +This feature is not enabled by default. +Any disabled world in the prisonCommandHandler configs within config.yml, could also shutdown the prison placeholders in that world if enabled. +The placeholder text will be replaced with just an empty string. -* Improved some of the `/prison support submit` features to include more of the newer data that prison is using. +* **Prestiges: Bug fix. If no prestige rank, then prevent a NPE on a simple check.** +Totally thought this was fixed a while ago? -* Updates to a number of libraries that prison uses: -placeholderApi: v2.10.9 to v2.11.2 -XSeries: v9.0.0 to v9.2.0 -item-nbt-api: v2.10.0 to v2.11.1 +* **AutoFeatures BlockInspector: Fixed a bug with not negating a condition... was causing some problems since it was misreporting the results.** -* Removal of support for MVDW placeholders since it's not able to support some of prison's advanced features, plus it's 100% redundant since PlaceholderAPI works in conjunction with it. No loss of service since PAPI is a better solution and works with MVDW. +* **AutoFeatures: Add support for the XPrison enchantments.** +Please be aware that event priorities must be adjusted. You can change prison's event priorities, but XPrison is hard coded to NORMAL So to get this work, you may have to adjust prison's priorities so it is after XPrison's. +We cannot support XPrison especially if their event priorities become a problem, or causes a problem. -* Added a Prison Backup feature that can make a backup of all the settings within prison's plugin directory (small zip file backups). It is setup to make a backup whenever it detects a change in the prison versions. In the future, it could be automated to make snapshots of all settings and player status so there can be abilities to "rollback" to a prior instance. +**v3.3.0-alpha.15c 2023-07-30** -* Added new translations: Finnish, Chinese, +* **RevEnchants: added additional logging and details if there is a failure trying to hook into the RevEnchant's events.** +Trying to see if there is additional causedBy information. -* Enhanced the player GUIs for mines and ranks to use NBT to control the options to simplify how the options work. Eliminated a lot of old code and added more flexibility. +* **ranks autoConfigure: Major enhancements to add more prestige ranks.** +Added a lot more informatio to the command's help: `/ranks autoConfigure help`. +More options have been added: prestiges prestiges=x prestigesCost=x prestigesMult=x. +Now able to add more prestige ranks without impacting ranks or mines. +Example to add up to 50 new prestige ranks: `/ranks autoConfigure force presetiges prestiges=50` -* Enable the sellall command to be ran from the console or from a prison command. +* **Sellall: Rearrange the sellall commands so they are better organized and updated the help text so its also meaningful.** -* Enhanced the debug logging detail related to the auto features. Provides better logging for troubleshooting. +* **sellall & autosell: auto sell was not working correctly within auto manager.** +Also fixed the user toggle on auto sell so players can turn off autosell when they need to. -* Using a static global setting for decimal formatting to better control how numeric formatting works with various language settings. +* **Sellall: clean up some of the help for a few sellall features and expand on the details. ** -* Able to now control suffocation in the mines, so you can now allow players to die if they logged out within a mine and they log back buried in rock. +**v3.3.0-alpha.15b 2023-07-28** -* Able to control mine reset teleportation controls. +* **Prevent a NPE if the target block is not found within the mine's settings.** -* Added direct support for translating placeholders through the Prison API so its easier to use externally through another plugin. +* **Mine Bombs: Found an issue with the bomb settings for allowedMines and preventMines, and fixed it.** +There is a global setting in config.yml under the settings: `prison-mines.mine-bombs.prevent-usage-in-mines` to disable all mine bombs from working in those mines. The bombs can then be individually added by setting adding mine names to the bomb configs settings for `allowedMines` and `preventedMines`. If a mine is included on a bomb's allowedMines setting, it will override any global setting. -* Now able to set a prestige rank tag to use for players that do not have a prestige rank. This allows for better customization for chat prefixes. +* **Fixed an issue with BRICKS being mismatched to BRICK. This is an XSeries bug.** -* Fixed a bug when trying to move a mine from one world to another world. There was a conflict with an internal value not being cleared/reset. +* **TopN: TopN was not being disabled correctly for when ranks were disabled.** +This now properly checks the PrisonRanks to see if the ranks module is active or not. The prior code was not being as detailed. -* Fixed a Prison Mine Bomb bug that was making them incompatible with bukkit 1.8.8. +* **Prison support: Added more color related test. Changed the color schema name from 'madog' to 'prison'.** -* Fixed a bug with how a vector's length was being calculated. Not sure how frequently this would have been used. +* **Mines set tracer: Update the command to add options for 'clear' the whole mine, and 'corners' where it clears the whole mine but puts the tracer only in the corners.** +The default option of 'outline' is the default value, and if 'clear' or 'corners' is not set, then it will default to the standard outline, or tracer. -* Refactoring Prison Backpacks. Getting ready to hook them up to a new internal backpack cache to improve performance. Not yet completed. +* **Enable all Ranks to be used with the sellall rank multiplier.** +It used to be limited to just prestige ranks, but there has been requests to expand to all ranks. -* Fixed bug with /rankupmax and rewrote prestiges to better align it with the ranks module instead of relying upon the GUI code to manage it. +* **Fixed a color code conflict in the ranks list when displaying the default rank.** +It wasn't wrong, but it was showing incorrectly. Added a reset `&r` and that fixed it. Almost like too much nesting got in the way. -* Enhanced many mine and rank commands to apply changes to all ranks or all mines with one command to make it easier to customize prison. +* **Prison Support: Support HTML file: Added a color test to prison, color matched on the console's colors to provide an accurate reproduction and match with the console.** +Added the ability to support themes: console is the primary, with Madog being an alternative. Can have others themes too. +Fixed a few layout issues. Added the ladder listing, which did not exist before. Setup the placeholders for the hyperlinks... they will be added next along with the auto generation of a table of contents. -* New feature setting (optional): Forced rankup as soon as the player earns enough money through sellall. +* **Prison Support: More enhancements to the html save file.** +Instead of calling the four `/prison support submit` commands, they are all now generated from within the same function. This will allow the collection of all hyperlinks to generate a tabl of contents. +Improvements to the layout of some of the items in report. -* New feature setting (optional): Forced sellall before performing a prestige. +* **Prison Support: Enabling the initial save file to an HTML file.** +Color codes are working great, but needs some tweaking. +The framework for hyperlinks are inserted in most locations... they are just double pipes surrounding 2 or 3 words. I will generate a series of classes that will auto generate hyperlinks and table of contents based upon these encodings. -* New feature setting (optional): Prevent access to prior mines when ranking up. This foces the player to only have access to mines that are linked to the current rank. This feature allows the use of Mine and TP access by rank instead of having to setup complex settings with perms through a permission plugin. +* **Prison Support: More setup of the new SupportHyperLinkComponent, but mostly the java docs which explains it pretty well.** ---------------------------- +* **Prison Support: Setup the Platform with the function to get the related Rank name or Ladder name, based upon the save file's name.** +This is used to reverse engineer which rank or ladder is tied to a give file, without having to read the file. + + +* **Prison Support: Start to setup an alternative support file target, of an html file.** +This file will also convert minecraft color codes to html colors. + + +* **PrisonPasteChat: change the exception to just Exception so it can capture all errors.** +The server has been down for the last two days and so other errors need to be caught. + + +* **If at last rank, show a message to tell the player that.** + + +* **Added a few more items to the default list of items in sellall.** + + +* **Added new feature to prevent mine bombs from being used in mines.** +A specific mine bomb can have a list of included mines, which overrides any exclusions. The mine bombs can be excluded from specific mines too. +There is also a global disallowed mine list that will apply to all mine bombs, its in the config.yml file with the setting name of: + prison-mines.mine-bombs.prevent-usage-in-mines +There is a global setting in config.yml under the settings: `prison-mines.mine-bombs.prevent-usage-in-mines` to disable all mine bombs from working in those mines. The bombs can then be individually added by setting adding mine names to the bomb configs settings for `allowedMines` and `preventedMines`. If a mine is included on a bomb's allowedMines setting, it will override any global setting. + + +* **The Platform function getConfigStringArray should be a List of Strings for the return value, so updated the result type to reflect the correct setting.** + + +* **Bug fix: If a sellall transaction is null, then it now returns a zero since nothing was sold.** + + +* **More adjustments to the PrisonDebugBlockInspector for readability.** + + +* **Auto features not being fully disabled when turned off.** +There was an issue with `/prison reload autoFeatures` enabling itself when it should have been off. + + + +** v3.3.0-alpha.15a 2023-07-16** + + + + +* **Enhance Prison's debug block inspector to fix an issue with running it multiple times for one test.** +Reformatted the layout so each plugin is now using only one line instead of two, and added the duration of runtime in ms. + + +* **SellAllData: The transaction log: Enhanced the itemsSoldReport by combining (compressing) entries for the same PrisonBlock type.** +This will make it easier to review since there will be only one entry per PrisonBlockType. + + +* **Auto Features AutoSell fix: There were situations where mine bombs that are set with the setting autosell was not being sold.** +Found a conflict with the logic of enabling autosell within the auto pickup code. There are four ways autsell could be enabled, and a couple were incorrectly mixed with their logic. +Debug mode is now showing drop counts before and after adjustments from the fortune calculations. + + +* **Prison tokens: expanded the error messages for playing not being found to the set and remove functions for the admin token commands.** + + +* **Prison Tokens: bug fix: Ran in to NPE when an invalid player name is used.** +The message text needs to be stored in the lang files. + + +* **Fixed a bug with using the wrong player object within auto feature's autosell.** + + +* **Update the prison API to add direct support for payPlayer function (various options).** + + +* **Prison Multi-Language Locale Manager: Updated all language files to include information about the new `*none*` keyword.** +This keyword is case insensitive and will return an empty string for that message component if it's part of a compound message. If the message is supposed to be sent to a player, it will be bypassed and nothing will be sent. + + +* **Prison Multi-Language Locale Manager: Possibly fixed a few issues with setting messages to "blanks". If the text of a message is removed, and set to an empty string, it should not be used.** +There was a situation where a zn_TW language file was set to an empty string and it was falling back to the en_US version. +I found that there was a bug with a sendMessage() function to a player that was not bypassing the message like the other functions were doing. +Also in the code where it was calculating the Locale variations, it was not accepting a blank as the final input. This was fixed. +Also, to be clear, or more specific, I added a new keyword `*none*` to serve the same purpose. So either an empty string can be used, or that new `*none*` key word. +* **More work on getting the new world guard sub-projects hooked up and functional in the build with gradle.** + + +* **Update the PrisonSpigotAPI to include a lot of new api endpoints for accessing sellall related functions.** + + +* **Sellall: Expanded the functionality of the SellAllData obejects to indicate if the items were sold.** + + +* **New sellall features: 'sellall valueof' calculates the value of everything in the player's inventory that can be sold. '/sellall valueofHand' calculates what is held in the player's hand.** + + +* **Major rewrites to sellall to utilize more of Prison's internal classes and to get away from XMaterial since it cannot handle custom blocks.** +A lot of sellall code has been eliminated, but no loss in functionality. Actually new functions and enhancements have been added. +Eliminated the two step process of selling... where it first calculated the values, then after the fact, would try to remove the items with no "validation" that the items removed were the items that calculated the sales amount. +Sellall commands: moved the '/sellall trigger add' and '/sellall trigger remove' to under the '/sell set' section since they were hidden because '/sellall trigger' was a command and many did not realize they have to use the 'help' keyword to show the others. + + +* **Updated Prison's PlayerInventory to include 'contents' and 'extraContents' to match the bukkit PlayerInventory object.** +Within the SpigotPlayerInventory class, overrode the behavior of removeItem to ensure that obscure inventory locations are being removed, since there was a bug where you can get all inventory items, then remove them, and they would not remove all occurrences of the items stacks that were initially returned, such as when someone is wearing an item as a hat, or holding something in one of their hands. + + +* **Allow additional parameters to be passed on the gradlew.bat command; needed for additional debugging and etc...** + + +* **Add new salePrice and purchasePrice to the prison Block.** + + +* **Sellall : remove the disabled worlds setting in the configs since it is obsolete and never used.** +The correct way to disable prison in specific worlds is by using the config.yml settings for prisonCommandHandler.exclude-worlds. + + +* **Bug fix... this is a continuation of a prior issue of prison commands not being mapped to their assigned command name by bukkit when prison's command handler registers them.** +This was an issue with another plugin that registered `/gui` before prison was able to, so then all of prison's gui commands were mapped to `/prison:gui`. So where this was an issue was with `/prestige` trying to run the gui presetige confirmation which was trying to kick off a GuiPlus command as a result of this improper mis-match. +Tested to confirm it is now functional. Changed all occurrences that I could find that also needed to be mapped. + + +* **Start to setup support for WorldEdit and WorldGuard.** + + +* **Setup a way to pull a config's hash keys.** +These would be used to dynamically get all settings within a hash. + + +* **Fixed an issue with prison commands being remapped, but other commands within prison were not using them.** +This tries to find the remapped command for all commands by updating the SpigotCommandSender.dispatchCommand(). + + +* **Fixed an issue where the setting isAutoFeaturesEnabled was not being applied to the permissions which resulted in the perms always being enabled when OPd.** + + + + +* **2023-07-07 v3.3.0-alpha.15 Released** + + + +See [Prison Change log v3.2.3-alpha.15](prison_changelog_v3.3.0-alpha.15.md) + + + +**Prison v3.3.0-alpha.14 2023-01-23** + + +See [Prison Change log v3.2.3-alpha.14](prison_changelog_v3.3.0-alpha.14.md) + + + +--------------------------- diff --git a/docs/knownissues_v3.2.x.md b/docs/knownissues_v3.2.x.md index 2f4d95873..9574ecb67 100644 --- a/docs/knownissues_v3.2.x.md +++ b/docs/knownissues_v3.2.x.md @@ -7,6 +7,8 @@ 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. +* **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** + * [Known Issues - Resolved](knownissues_v3.2.x_resolved.md) diff --git a/docs/knownissues_v3.3.x.md b/docs/knownissues_v3.3.x.md index b51f664f2..1d6b7bff6 100644 --- a/docs/knownissues_v3.3.x.md +++ b/docs/knownissues_v3.3.x.md @@ -4,6 +4,8 @@ These known issues are an informal list of concerns and bugs. Also includes some wish-list items too. +Not everything is logged here. Please see the changelog for fixes and new features that were actually added. + These are notes for personal references. These are not intended to explain anything useful, but they do track some issues and perspectives that may not be fully expressed in the change logs because initial impressions may not turn out to be the actual problem or the final course of changes and enhancements. diff --git a/docs/prison_changelog_v3.3.0-alpha.14.md b/docs/prison_changelog_v3.3.0-alpha.14.md index e995dab6c..202b8f027 100644 --- a/docs/prison_changelog_v3.3.0-alpha.14.md +++ b/docs/prison_changelog_v3.3.0-alpha.14.md @@ -4,7 +4,7 @@ ## Build logs - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** - - [v3.2.0 through v3.3.0-alpha.15](prison_changelogs.md) + - [v3.2.0 through v3.3.0-alpha.16](prison_changelogs.md) These build logs represent the work that has been going on within prison. diff --git a/docs/prison_changelog_v3.3.0-alpha.15.md b/docs/prison_changelog_v3.3.0-alpha.15.md index 80f7b0ef7..44cf900a5 100644 --- a/docs/prison_changelog_v3.3.0-alpha.15.md +++ b/docs/prison_changelog_v3.3.0-alpha.15.md @@ -4,7 +4,7 @@ ## Build logs - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** - - [v3.2.0 through v3.3.0-alpha.15](prison_changelogs.md) + - [v3.2.0 through v3.3.0-alpha.16](prison_changelogs.md) These build logs represent the work that has been going on within prison. @@ -16,7 +16,11 @@ These build logs represent the work that has been going on within prison. The following is a highlight of changes for the alpha.15 release since the alpha.14 release. --Full support for 1.20.x including the heights and blocks. +- Full support for 1.20.x including the heights and blocks. + + +- Added support for Java 20. + - MineBombs - Added a new field specifically for use with item names which supports color codes. @@ -45,7 +49,7 @@ The following is a highlight of changes for the alpha.15 release since the alpha - Fixed how NBT-api is being shadowed and used to get it to work properly with Spigot 1.20.x. -- Minor fixes and enchancements: blockEvents, autoFeatures and monitor priorities, GUI Player Mine config options, prevent GUI configs from loading twice, when mining now can control non-prison placed blocks to pass through to be handled by bukkit, fix autosell when disabled, hooked up support for minecraft stats to track block mining, prevent zero drops if calcs are less than 1, fix sellall trying to sell an invalid stack, fix prison utils potion effects when no player is provided, support for ExaltedEconomy, able to bypass adding new players on startup, updated Prison's jar reporter to identify Java versions 19, 20, and 21, clearified help on `/rankup` and `/presetige`, update of how topN is being processed, added topN stats which reports some of the core info. +- Minor fixes and enhancements: blockEvents, autoFeatures and monitor priorities, GUI Player Mine config options, prevent GUI configs from loading twice, when mining now can control non-prison placed blocks to pass through to be handled by bukkit, fix autosell when disabled, hooked up support for minecraft stats to track block mining, prevent zero drops if calcs are less than 1, fix sellall trying to sell an invalid stack, fix prison utils potion effects when no player is provided, support for ExaltedEconomy, able to bypass adding new players on startup, updated Prison's jar reporter to identify Java versions 19, 20, and 21, clarified help on `/rankup` and `/presetige`, update of how topN is being processed, added topN stats which reports some of the core info. diff --git a/docs/prison_changelog_v3.3.0-alpha.16.md b/docs/prison_changelog_v3.3.0-alpha.16.md new file mode 100644 index 000000000..9df2c680e --- /dev/null +++ b/docs/prison_changelog_v3.3.0-alpha.16.md @@ -0,0 +1,646 @@ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +## Prison Build Logs for v3.3.x + +## Build logs + - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** + - [v3.2.0 through v3.3.0-alpha.16](prison_changelogs.md) + + +These build logs represent the work that has been going on within prison. + + +# 3.3.0-alpha.16 2023-11-18 + + + +The following is a highlight of changes for the alpha.16 release since the alpha.15 release. + + +* Bug fix: A library that prison uses broke with the release of Spigot 1.20.2 due to new parameter overloading that spigot introduce, that resulted in ambiguous parameter failures. + + +* Auto Features: Many updates and enhancements. + + +* Sellall: Many updates and enhancements from API to GUI and autofeatures integration. + - Streamlined to work with prison's custom blocks instead of just XMaterial items. + - New functionality to improve managing what's been sold, or just getting their value. Extended a lot of this new functionality to the prison APIs. + - Added many new default items + - Changed all of the commands under sellall to better organize like commands in to sub-commands + - Rank multipliers now works for all ranks, not just prestiges. New commands to reset all multipliers for ladders (which is great if you have a few thousand prestige ranks). + - If blocks could not be sold through auto features autosell, it will generate debug mmessages so it's easier to track why blocks are not being sold. + - Able to disable the "nothing to sell" message so it stops spamming the player. + - For different server configs, where there are issues that prevent autosell from being used, such as other plugins placing blocks in the player's inventory, you can now force a sellall after the block break event is finished being processed. + - Sellall Multipliers - Many new features and commands. Explore with `/sellall multiplier` and use the keyword `help` on each command for more details. The multiplier list can use different column widths to better support thousands of prestige ranks. + + + +* Prison's command handler: Updates and a few enhancements. + - Worlds that are disabled in config.yml prevents prison's command handler from working in those worlds, thus shutting down any and all aspects of prison in those worlds. Use carefully since no warnings will be shown in those worlds that prison is ignoring all commands issued from within those worlds. + + +* Fixed an issue with the player's inventory not matching prison's internal code vs bukkit's. + + +* Expanded Prison's APIs so its easier to use prison's internals within other plugins for the most flexibility in customizing your servers. + + +* Multi-language support files now supports: + - `*none*` keyword to suppress any text. Returns an empty String. + - Now supports line breaks within messages. Use `{br}` which is similar to the html break: `
` but cannot use the `<` or `>`. The `{}` is typical of placeholders. + + +* Improvements to Prison's debug mode and block inspector to make is easier to address issues. + - Debug mode can now be tied to a single person to prevent the console from being spammed + + +* Prison Mine Bombs - Can now identify which mines specific bombs can be use in, or excluded from. Includes a global setting in config.yml so individual bombs do not need to be configured to be excluded from certain mines. + + +* Prison support - New features + - Adding a new HTML bases support file. More work needs to be done with it before making it the primary tool. + - Changed servers for submitting support help files... they are not encrypted and password protected. And they are purged in 7 days. + + +* Mines - + - Mine tracer now has an option to 'clear' the whole mine, mark jjust the 'corners', or the standard full tracer. + - Found and fixed a sync task that was a possible cause of jitters. This helps when the server is under a heavy load. + - Added a `/mtop` command. `/mines top` which teleports a player to the top of the mine they are in. + + + +* Auto Configure - Major changes to add more default prestige ranks, and the ability to go back and add more ranks after your server is up and running without harming anything. + - Added support to reset all rank cost multiplier and rank costs to apply to all ranks on a ladder. + + +* XPrison Enchantments - Added some basic support for using the XPrison enchantments. There are some limitations, and not all enchantments will work perfectly. + + +* Placeholders - + - Disabled all placeholders in disabled worlds. + - New placeholder attribute to pass a player name to force a non-player placeholder request to use the specified player. This is useful for some scripting languages and other plugins. + + + +* Auto Manager - + - New fortune type: percentGradient. An alternative fortune calculation that is designed to be more linear distribution, based upon the tool's fortune. + - Able to use TokenEnchant's fortune level. + + +* BlockConverters - Starting to use some minor features. The first being Event Triggers where a given block can force prison to trigger another plugin and allow that plugin to handle all processing for that block. Example is using a lucky block. + + + +* **Prison compatibility: Added support for block metadata customModelData.** + - This is only compatible with spigot 1.14.x and higher. + - Supported in prison mine bombs so you can customize the bomb's texture + + + +* Prison performance improvements: + - More options to fine tune control of the player cache, mine reset control, economy cache, etc... + - Need to produce a document that covers performance optimization for prison + - Some default settings have been changed to encourage better performance out-of-the-box + + + + + + + +# 3.3.0-alpha.16 2023-11-18 + + +* **Fixed an issue with ranks being disabled. It now skips over this processing when ranks are disabled.** + + + +* **Modules: Changed the way some of the module management is used to help prevent errors when a module is disabled.** +Suppress disabled modules from the placeholder list... only Ranks and Mines, which covers all of the placeholders. + + + +* **Sellall: Standardize how sellall is being checked to see if it's enabled.** +There are still a few ways it can be improved, but this is a step in the right direction. +There was a problem with the older way things were being handled that was causing an NPE with the SpigotPlayer, which was brought to my attention by DinoFengz, but I noticed there were other problems that needed to also be addressed. + + +* **Economy support for CoinsEngine: support has been initially added**, but it is unsure if it is working correctly. This request originated from pingu and they said it's not working, but has not provided any more information. Unsure how it's not working, or if they cannot use it the way they originally envisioned because sellall cannot support different currencies for different items within sellall. +Because of the lack of an API jar to be used, a new sub-project 'prison-misc' was created to be able to generate a pseudo-shell api for the CoinsEngine plugin. This pseduo api jar is used strictly to allow the successful compiling of the prison's economy hooks for CoinsEngine. +NOTE: I have not heard back from pingu to know if this is working. If you try to use this plugin and you have issues, please contact me on our discord support server. + + +* **Block Converters: Change the usage to Player instead of RankPlayer since if ranks are disabled then RankPlayer could not exist.** + + +** 3.3.0-alpha.15h 2023-11-05** + + +* **Player Cache: Put some of the player cache numbers in to the config.yml file so they can be fine tuned if desired.** +See the changes to config.yml for information to what the new setting controls. + + +* **GUI: Add support for changing the gui item names for Ranks and Mines. Ranks can now set their material type too.** + + +* **Updated nbt-api and fixed a new issue that was introduced with mc 1.20.2.** + + +* **Placeholder attribute time: add the time attribute to 4 more placeholders.** + + +* **Auto Sell: Bug fix for full inventory when auto sell is toggled off, which was incorrectly selling the player's inventory.** + + +* **Prison Debug: Added support to target some debug logging to a specific player.** +When enabled, it will ignore all other players. Not all debug messages have been hooked up. More can be added upon request. +When debug mode is disabled, it will remove the debug player name. + + +* **Placeholders: Added support for a new placeholder attribute to better format time based placeholders.** + + +* **Placeholders: Added the ability to provide a shorted output of the command `/prison placeholders test` so it only shows the command header and the results.** +Use the '-s' flag as in: '/prison placeholders test -s' + + +* **Placeholders: bug fix: If using the placeholder attribute for an off line player, it would cause an error when checking if the player was in a disabled world.** + + +* **SellAll messages: Cleaned up some of the US EN messages related to the sellall command.** + + +* **Bug: sellall auto sell enabled messages reversed.** +The command to enable and disable the auto sell feature was reversed, so when turning off, it would report that it was just turned on. And on when it was turned off. + + +**v3.3.0-alpha.15g 2023-10-03** + + +* **Player Economy Cache Delay: Add the ability to change the player economy cache delay. Default value is 3 seconds, or 60 ticks.** + + +* **Prison version: Improve the content of the auto features details.** + + +* **Placeholders: Added the ability to specify a player name in all placeholder attributes.** +This can allow the use of placeholders that are player centric in plugins that cannot support player based placeholder requests. + + +* **Autosell: Setup the SpigotPlayer object to support functions to identify if the player has autosell enabled. This is used in a couple of places to eliminate redundancy.** +Fixes a problem with the block break event not also checking to see if the player has toggled their autosell status for the forced sell after the event is processed, and also the delayed sell. + + +* **Cleanup the '/ranks list' to add mines and better format the name, tag, and cost.** +Also removed rankId which is not important anymore. + + +* **Auto features: change a few of the new line breaks so there are fewer.** + + +* **Changed the default color code from `&9` (dark blue) to `&b` (light blue) for debug logging since the dark blue could be difficult to see on some consoles. + + +**v3.3.0-alpha.15f 2023-09-24** + + +* **TopNPlayer: Task could not startup if ranks are enabled but there are no default ranks.** +Log a message in the console that the task cannot start because ranks are enabled and there are no ranks. +Request that Ranks module is disabled, or add default ranks and then restart the server. + + +* **Prison Support: Added a more secure method and server (privatebin) for submitting server information under prison support submit commands.** +Can now control some of the settings that are used, including password, in the config.yml file. +May need to refresh config.ymml to see now settings. + + +* **MineBombs: validate all mine bombs upon server startup to validate the sound effects, visual effects, and shape based upon the version of spigot that they are running.** +This mostly is to clean up the default mine bombs where they have sound and visual effects for versions of spigot so something will happen. This removes the invalid ones for the version so there are less errors at run time. + + +* **MineBombs: Add support for customModelData for the item used for the bomb.** +This will only work on spigot version 1.14.x and higher. + + +* **Prison compatibility: Added support for block metadata customModelData.** +This is only compatible with spigot 1.14.x and higher. + + +* **Ranks Ladder resetRankCost: Added a new parameter to provide an exponent which is used as a Math.pow() function over the base rank cost calculations.** +This can help increase the rank costs for higher ranks. +Default value is 1.0 so it does not apply unless it is specifically changed. + + +* **Update the Double vs BigDecimal example. Increased from 25 to 35 iterations, and expanded all columns to adjust for the wider output.** + + +* **Block Converters: event triggers: More work. Got it working to the point that it's ready for production.** +The way it is right now, any block that is in an event trigger, will be excluded from all explosions. They will remain unbroken in the mine. +The players can then break them directly to trigger the events. Eventually I may allow processing within an explosion event, but right now it's not making sense to process 100+ triggers all at one time for huge explosions... the other plugin that's being "fired" may cause lag trying to process that many at one time. + + + +* **BlockConverters eventTriggers: Fixed the handling of event trigger blocks so they can be ignored within an explosion event. Now works.** +Still have to process the event trigger blocks in explosions for when they need to be triggered. + + +* **Sellall command: '/sellall set delay' - fixed the description which had a typo in the description.** + + +* **SpigotPlayer: fixed a problem where the object was expected to be comparable.** + + +* **BlockConverters eventTriggers: Add the support for explosion events to all of the explosion event handlers.** + + +* **BlockConverters EventTriggers: Setup the next phase of handling where blocks in explosions can be ignored.** + + +* **BlockConverters EventTriggers - setup the PrisonMinesBlockBreakEvent to allow an event to identify if the primary block must be forcefully removed**, which is only used right now with event triggers, and would remove the block when handling a MONITOR event, which normally does not remove any blocks. + + +* **BlockConverters EventTriggers: Setup more controls within the settings of a blockEvent.** +Setup the ability to control processing of drops: if disabled, it will treat the block event as a MONITOR. This allows the block to be counted correctly. +Setup the ability to ignore the block type within all explosions, so each block would have to be broken individually. +Setup the ability to remove the block without dropping anything since another plugin would have already processed the block, so nothing would remain to be done with it. + + +* **Mines block edit - Found a problem where if you are trying to edit a block and the name does not match, it was causing an error.** Now reports that the block name is invalid. + + +* **Block Converters - Event Triggers - Had issues with block names not matching, so using all lower case. When using an event trigger it now logs the debug info to the console.** +This will need more work, such as block removal and logging as if it were a MONITOR priority. +At this point, we are testing to confirm that the event is actually being triggered. So far it looks like it is working as intended. + + +* **Block Converters: Start to hook up block converters to auto features.** +Changed how block converters were structured to get them to work with the prison environment. +Hooked up the Block Converter Event Trigger to the bukkit BlockBreakEvent. Explosions are not yet covered, will add support for them if this appears to work. + + +* **Update docs and some command descriptions to make them a little more clearer as to what they do.** + + +* **sellall multipliers list: Added 2 options to control the number of columns displayed with 'cols=7' and also only show multipliers for a single ladder if that ladder name is provided in the options.** + + +* **sellall multiplier list: Now applies a sort order to the ranks, grouping by ladders.** It groups by ladders, and then lists the ranks in rank order, within each ladder. + + +* **sellall multiplier addLadder: added more comments to the command's help, and added defaults to the parameters.** + + +* **SellAll multipliers: Increased the number of columns for the listing to 8 columns instead of 5.** May need to expand it even more so if there are thousands of ranks, it can be better managed. +New command: `/sellall multiplier deleteLadder` deletes all multipliers for that ladder. +New command: `/sellall multiplier addLadder` adds multipliers for all ranks on the ladder. + + +* **Ranks Auto Configure: Fixed message format when options are not valid so it's better understood what's wrong with the command.** +The parameter names are case sensitive, but added a fallback mapping to lowercase so there is a higher chance of matching the correct commands. +Had to move the location of the 'prestigeMulti=' parameter to be evaluated before 'multi=' parameter since it was taking over the `prestigeMulti=` parameter. + + +* **Update the rank's getPosition() java docs to better clarify what it is.** + + +* **Ladders: Added a new command to reset all rank costs for a given ladder: '/ranks ladder resetRankCosts help'** +This will allow a simple and easy change to all rank costs within a given ladder even if there are many ranks, such as the presetiges ladder which could have thousands of ranks. +These calculations are similar to how the `/ranks autoConfigure` will set them up. + + +* **Prison logging: When line breaks are applied in log messages, it will no long include the prison template prefix with the message to reduce the clutter and make it easier to read multi-lined content.** +The line break placeholder is '{br}', similar to the html element BR. + + + +**v3.3.0-alpha.15e 2023-09-03** + +* **Prison messages: Expanded the use of prison message line breaks, `{br}` in both console messages and sending messages to player.** +Auto Features: Added line breaks to the existing block break debug info since it's very long and difficult to read. + + +* **Mine wand debug info: Slightly alter the printing of the details to make it easier to read.** + + + +* **AutoFeatures and prison version: I have no idea why I added an auto features reload when doing prison version. Removed.** +Best guess at this moment is that it was to test something. + + +* **Prison GUI: When disabled through the config.yml 'prison-gui-enabled: false' there were still some commands that were being registered with the '/gui' root.** +As a result, prison was taking over the use of the command '/gui' that was trying to be used by other plugins. +This fix tries to isolate the GUI commands from backpacks, prestiges, and sellall, to make sure they cannot be registered if GUI is disabled. +Had to create new classes to allow the isolation when registering the commands. + + +* **AutoManager: percent gradient fortune: Changed the calculations to use doubles instead of integers.** + + +* **Slime-fun: Moved a lot of the settings for it to the config.yml file instead of hard coding them.** +Now the messages can be turned off, and the boosters can now be added to, and changed. + + +* **Sellall: Fixed a bug with spigot 1.8.8 where bricks were not able to be sold correctly.** +The issue is with XBlock not correctly mapping brick and bricks to the correct bukkit 1.8 materials. It may be close, or accurate, but when converting to a bukkit item stack, it fails to map back to the same objects. +Sellall was not using the prison compatibility classes, and those classes for 1.8 had to be updated too. + + +* **AutoFeatures: New option to use TokenEnchant to get the enchantment level through their API instead of using the bukkit functions to get the fortune.** + + +* **AutoFeatures: Added a debug statement when player autosell has been toggled off by the player, since it may look as if autosell is not working correctly.** +Wrapped the notice in a WARNING color code so it stands out in the console with it being red. + + +* **AutoFeatures: Updated the gradient fortune to fix a problem with not setting the bonus block counts correctly.** + + +* **AutoManager: Added a new fortune type: percentGradient.** +This fortune calculation is an alternative to the extendedBukkit and altFortune calculations. +This fortune calculation applies a linear distribution based upon the player's tool's fortune level versus the maxfortuneLevel and the maxBonusBlocks. + + +* **Added a `/mines top` command, alias `/mtop`, which will tp a player to the spawn location of the current mine they are in. ** +If they are not in a mine, then it will tp them to a mine tied to their current default rank. + + +**v3.3.0-alpha.15d 2023-08-16** + + +* **Mine reset time: Found a conflict with the setting '*disable*' being ignored.** +It's been fixed. + + +* **BlockBreak sync task: Found a possible cause of jitters, or visual appearance of lag.** +Basically, need to check the block to ensure it's not already AIR before setting it to AIR. This could happen if there is a heavy load on the server from other plugins, or from bukkit itself, and bukkit naturally breaks the block before prison's sync task can get to it. +Prison submits the sync task to run "next" in the future, but if there are other tasks trying to run, and if they cause a longer delay, then it can appear to be laggy. + + +* **AutoFeatures: Expand the number of features being reported to bstats.** +Removed a duplicate comment in the autoFeatures config file. + + +* **AutoFeatures: Add comment on autosell by perms so it's clear what setting are needed.** +Also added a setting of 'false', in addition to 'disable', which disables the permission based autosell. + + +* **AutoFeatures XPrison event listener: Fixed a bug that was ignoring the first block in the exploded block list.** + + +* **AutoFeatures: Added the ability to force a delayed inventory sellall at the end of handling a bukkit BlockBreakEvent. This is in addition to the other instant sellall at the end of the bukkit BlockBreakEvent.** +This has the ability to set a delay in ticks before it is fired. +If a task was submitted for a player, then future tasks cannot be submitted for that player until the submitted sellall task was finished running. +This was added to help cover situations where third party plugins are trying to add additional bonus drops to the players, but after prison is done handling the events. + + +* **AutoFeatures: Added the ability to force an inventory sellall at the end of handling a bukkit BlockBreakEvent.** +This was added to help cover situations where third party plugins are trying to add additional bonus drops to the players. + + +* **auto features: setup a sellall function on PrisonMinesBlockBreakEvent so it can be easier to utilize from other functions.** + + +* **AutoFeatures SellAll: Added the ability to disable the "nothing to sell" message without effecting the other settings.** + + +* **auto features: Add the calculated autosell to the dropExtra function to force autosell if it should happen to have extra drops left over (it never should).** + + +* **Auto Features: If autosell is enabled and there are any leftover blocks that was not sold, it will now generate an error message and if prison debug mode is turned off, then it will force the logging of the transaction.** +This forcing the logging can be turned off in the auto features configs. +Expanded the logging to change the color on some of the more important warnings and failures so they stand out. +Also reworked some of the log details to eliminate redundancy and clarify what's being logged. + + +* **AutoFeatures: Added support for XPrison's enchantments... forgot to add the API jar which is used to just compile prison (not used on servers).** + + +* **Prison Placeholders: Added support to disable placeholders in disabled worlds.** +This feature is not enabled by default. +Any disabled world in the prisonCommandHandler configs within config.yml, could also shutdown the prison placeholders in that world if enabled. +The placeholder text will be replaced with just an empty string. + + +* **Prestiges: Bug fix. If no prestige rank, then prevent a NPE on a simple check.** +Totally thought this was fixed a while ago? + + +* **AutoFeatures BlockInspector: Fixed a bug with not negating a condition... was causing some problems since it was misreporting the results.** + + +* **AutoFeatures: Add support for the XPrison enchantments.** +Please be aware that event priorities must be adjusted. You can change prison's event priorities, but XPrison is hard coded to NORMAL So to get this work, you may have to adjust prison's priorities so it is after XPrison's. +We cannot support XPrison especially if their event priorities become a problem, or causes a problem. + + +**v3.3.0-alpha.15c 2023-07-30** + + +* **RevEnchants: added additional logging and details if there is a failure trying to hook into the RevEnchant's events.** +Trying to see if there is additional causedBy information. + + +* **ranks autoConfigure: Major enhancements to add more prestige ranks.** +Added a lot more informatio to the command's help: `/ranks autoConfigure help`. +More options have been added: prestiges prestiges=x prestigesCost=x prestigesMult=x. +Now able to add more prestige ranks without impacting ranks or mines. +Example to add up to 50 new prestige ranks: `/ranks autoConfigure force presetiges prestiges=50` + + +* **Sellall: Rearrange the sellall commands so they are better organized and updated the help text so its also meaningful.** + + +* **sellall & autosell: auto sell was not working correctly within auto manager.** +Also fixed the user toggle on auto sell so players can turn off autosell when they need to. + + +* **Sellall: clean up some of the help for a few sellall features and expand on the details. ** + + +**v3.3.0-alpha.15b 2023-07-28** + + +* **Prevent a NPE if the target block is not found within the mine's settings.** + + +* **Mine Bombs: Found an issue with the bomb settings for allowedMines and preventMines, and fixed it.** +There is a global setting in config.yml under the settings: `prison-mines.mine-bombs.prevent-usage-in-mines` to disable all mine bombs from working in those mines. The bombs can then be individually added by setting adding mine names to the bomb configs settings for `allowedMines` and `preventedMines`. If a mine is included on a bomb's allowedMines setting, it will override any global setting. + + +* **Fixed an issue with BRICKS being mismatched to BRICK. This is an XSeries bug.** + + +* **TopN: TopN was not being disabled correctly for when ranks were disabled.** +This now properly checks the PrisonRanks to see if the ranks module is active or not. The prior code was not being as detailed. + + +* **Prison support: Added more color related test. Changed the color schema name from 'madog' to 'prison'.** + + +* **Mines set tracer: Update the command to add options for 'clear' the whole mine, and 'corners' where it clears the whole mine but puts the tracer only in the corners.** +The default option of 'outline' is the default value, and if 'clear' or 'corners' is not set, then it will default to the standard outline, or tracer. + + +* **Enable all Ranks to be used with the sellall rank multiplier.** +It used to be limited to just prestige ranks, but there has been requests to expand to all ranks. + + +* **Fixed a color code conflict in the ranks list when displaying the default rank.** +It wasn't wrong, but it was showing incorrectly. Added a reset `&r` and that fixed it. Almost like too much nesting got in the way. + + +* **Prison Support: Support HTML file: Added a color test to prison, color matched on the console's colors to provide an accurate reproduction and match with the console.** +Added the ability to support themes: console is the primary, with Madog being an alternative. Can have others themes too. +Fixed a few layout issues. Added the ladder listing, which did not exist before. Setup the placeholders for the hyperlinks... they will be added next along with the auto generation of a table of contents. + + +* **Prison Support: More enhancements to the html save file.** +Instead of calling the four `/prison support submit` commands, they are all now generated from within the same function. This will allow the collection of all hyperlinks to generate a tabl of contents. +Improvements to the layout of some of the items in report. + + +* **Prison Support: Enabling the initial save file to an HTML file.** +Color codes are working great, but needs some tweaking. +The framework for hyperlinks are inserted in most locations... they are just double pipes surrounding 2 or 3 words. I will generate a series of classes that will auto generate hyperlinks and table of contents based upon these encodings. + + +* **Prison Support: More setup of the new SupportHyperLinkComponent, but mostly the java docs which explains it pretty well.** + + +* **Prison Support: Setup the Platform with the function to get the related Rank name or Ladder name, based upon the save file's name.** +This is used to reverse engineer which rank or ladder is tied to a give file, without having to read the file. + + +* **Prison Support: Start to setup an alternative support file target, of an html file.** +This file will also convert minecraft color codes to html colors. + + +* **PrisonPasteChat: change the exception to just Exception so it can capture all errors.** +The server has been down for the last two days and so other errors need to be caught. + + +* **If at last rank, show a message to tell the player that.** + + +* **Added a few more items to the default list of items in sellall.** + + +* **Added new feature to prevent mine bombs from being used in mines.** +A specific mine bomb can have a list of included mines, which overrides any exclusions. The mine bombs can be excluded from specific mines too. +There is also a global disallowed mine list that will apply to all mine bombs, its in the config.yml file with the setting name of: + prison-mines.mine-bombs.prevent-usage-in-mines +There is a global setting in config.yml under the settings: `prison-mines.mine-bombs.prevent-usage-in-mines` to disable all mine bombs from working in those mines. The bombs can then be individually added by setting adding mine names to the bomb configs settings for `allowedMines` and `preventedMines`. If a mine is included on a bomb's allowedMines setting, it will override any global setting. + + +* **The Platform function getConfigStringArray should be a List of Strings for the return value, so updated the result type to reflect the correct setting.** + + +* **Bug fix: If a sellall transaction is null, then it now returns a zero since nothing was sold.** + + +* **More adjustments to the PrisonDebugBlockInspector for readability.** + + +* **Auto features not being fully disabled when turned off.** +There was an issue with `/prison reload autoFeatures` enabling itself when it should have been off. + + + +** v3.3.0-alpha.15a 2023-07-16** + + + + +* **Enhance Prison's debug block inspector to fix an issue with running it multiple times for one test.** +Reformatted the layout so each plugin is now using only one line instead of two, and added the duration of runtime in ms. + + +* **SellAllData: The transaction log: Enhanced the itemsSoldReport by combining (compressing) entries for the same PrisonBlock type.** +This will make it easier to review since there will be only one entry per PrisonBlockType. + + +* **Auto Features AutoSell fix: There were situations where mine bombs that are set with the setting autosell was not being sold.** +Found a conflict with the logic of enabling autosell within the auto pickup code. There are four ways autsell could be enabled, and a couple were incorrectly mixed with their logic. +Debug mode is now showing drop counts before and after adjustments from the fortune calculations. + + +* **Prison tokens: expanded the error messages for playing not being found to the set and remove functions for the admin token commands.** + + +* **Prison Tokens: bug fix: Ran in to NPE when an invalid player name is used.** +The message text needs to be stored in the lang files. + + +* **Fixed a bug with using the wrong player object within auto feature's autosell.** + + +* **Update the prison API to add direct support for payPlayer function (various options).** + + +* **Prison Multi-Language Locale Manager: Updated all language files to include information about the new `*none*` keyword.** +This keyword is case insensitive and will return an empty string for that message component if it's part of a compound message. If the message is supposed to be sent to a player, it will be bypassed and nothing will be sent. + + +* **Prison Multi-Language Locale Manager: Possibly fixed a few issues with setting messages to "blanks". If the text of a message is removed, and set to an empty string, it should not be used.** +There was a situation where a zn_TW language file was set to an empty string and it was falling back to the en_US version. +I found that there was a bug with a sendMessage() function to a player that was not bypassing the message like the other functions were doing. +Also in the code where it was calculating the Locale variations, it was not accepting a blank as the final input. This was fixed. +Also, to be clear, or more specific, I added a new keyword `*none*` to serve the same purpose. So either an empty string can be used, or that new `*none*` key word. + + +* **More work on getting the new world guard sub-projects hooked up and functional in the build with gradle.** + + +* **Update the PrisonSpigotAPI to include a lot of new api endpoints for accessing sellall related functions.** + + +* **Sellall: Expanded the functionality of the SellAllData obejects to indicate if the items were sold.** + + +* **New sellall features: 'sellall valueof' calculates the value of everything in the player's inventory that can be sold. '/sellall valueofHand' calculates what is held in the player's hand.** + + +* **Major rewrites to sellall to utilize more of Prison's internal classes and to get away from XMaterial since it cannot handle custom blocks.** +A lot of sellall code has been eliminated, but no loss in functionality. Actually new functions and enhancements have been added. +Eliminated the two step process of selling... where it first calculated the values, then after the fact, would try to remove the items with no "validation" that the items removed were the items that calculated the sales amount. +Sellall commands: moved the '/sellall trigger add' and '/sellall trigger remove' to under the '/sell set' section since they were hidden because '/sellall trigger' was a command and many did not realize they have to use the 'help' keyword to show the others. + + +* **Updated Prison's PlayerInventory to include 'contents' and 'extraContents' to match the bukkit PlayerInventory object.** +Within the SpigotPlayerInventory class, overrode the behavior of removeItem to ensure that obscure inventory locations are being removed, since there was a bug where you can get all inventory items, then remove them, and they would not remove all occurrences of the items stacks that were initially returned, such as when someone is wearing an item as a hat, or holding something in one of their hands. + + +* **Allow additional parameters to be passed on the gradlew.bat command; needed for additional debugging and etc...** + + +* **Add new salePrice and purchasePrice to the prison Block.** + + +* **Sellall : remove the disabled worlds setting in the configs since it is obsolete and never used.** +The correct way to disable prison in specific worlds is by using the config.yml settings for prisonCommandHandler.exclude-worlds. + + +* **Bug fix... this is a continuation of a prior issue of prison commands not being mapped to their assigned command name by bukkit when prison's command handler registers them.** +This was an issue with another plugin that registered `/gui` before prison was able to, so then all of prison's gui commands were mapped to `/prison:gui`. So where this was an issue was with `/prestige` trying to run the gui presetige confirmation which was trying to kick off a GuiPlus command as a result of this improper mis-match. +Tested to confirm it is now functional. Changed all occurrences that I could find that also needed to be mapped. + + +* **Start to setup support for WorldEdit and WorldGuard.** + + +* **Setup a way to pull a config's hash keys.** +These would be used to dynamically get all settings within a hash. + + +* **Fixed an issue with prison commands being remapped, but other commands within prison were not using them.** +This tries to find the remapped command for all commands by updating the SpigotCommandSender.dispatchCommand(). + + +* **Fixed an issue where the setting isAutoFeaturesEnabled was not being applied to the permissions which resulted in the perms always being enabled when OPd.** + + +* **2023-07-07 v3.3.0-alpha.15 Released** + + + diff --git a/docs/prison_changelogs.md b/docs/prison_changelogs.md index 2a221dcc9..f0badc17a 100644 --- a/docs/prison_changelogs.md +++ b/docs/prison_changelogs.md @@ -9,8 +9,9 @@ These are internal notes that may initially record ideas and issues. They may n reflect the final actions taken as expressed in the change logs below, so these may be insightful in to some of the evolutionary processes. -* [Known Issues - Open](knownissues_v3.2.x.md) -* [Known Issues - Resolved](knownissues_v3.2.x_resolved.md) +* [Known Issues - v3.3.x Open](knownissues_v3.3.x.md) +* [Known Issues - v3.3.x Resolved](knownissues_v3.3.x_resolved.md) +* [Known Issues - v3.2.x](knownissues_v3.2.x.md) ## Change logs @@ -21,6 +22,7 @@ These build logs represent the work that has been going on within prison. - Future updates will be under the v3.3.x release + - [v3.3.3-alpha.16 - 2023-11-18](prison_changelog_v3.3.0-alpha.16.md)   - [v3.3.3-alpha.15 - 2023-07-07](prison_changelog_v3.3.0-alpha.15.md)   - [v3.3.3-alpha.14 - 2023-01-23](prison_changelog_v3.3.0-alpha.14.md)   diff --git a/docs/prison_docs_000_toc.md b/docs/prison_docs_000_toc.md index 2221917bd..66e1cd54a 100644 --- a/docs/prison_docs_000_toc.md +++ b/docs/prison_docs_000_toc.md @@ -2,15 +2,14 @@
-*Documented updated: 2022-12-30* +*Documented updated: 2023-11-18* ## Project Related * **[Prison README](prison_readme.md)** High level information, plus how to use with gradle builds. * **[Prison License](prison_license.md)** GNU General Public License * **[Prison Change logs](prison_changelogs.md)** Detailed changes to prison. -* **[Prison Known Issues - Open](knownissues_v3.3.x.md)** Known Issues and To Do's. -* **[Prison Known Issues - Resolved](knownissues_v3.3.x_resolved.md)** Resolved Known Issues and To Do's. + * **[Prison Discord Server](https://discord.gg/DCJ3j6r)** Get help here. diff --git a/docs/prison_docs_010_setting_up_a_spigot_server.md b/docs/prison_docs_010_setting_up_a_spigot_server.md index 44751af85..700636b22 100644 --- a/docs/prison_docs_010_setting_up_a_spigot_server.md +++ b/docs/prison_docs_010_setting_up_a_spigot_server.md @@ -13,7 +13,7 @@ Buildtools also allows easy setup of many test environments since all you would need to do is to just change the version. -*Documented updated: 2023-01-14* +*Documented updated: 2023-07-24*
@@ -24,11 +24,11 @@ If you need more assistance, please search for online documentation since there are many good resources out there. * First install a copy of Java that is accessible from the command line. - - The current version of Java is version 17. Even if you are using jars and other plugins that were compiled with Java 1.8.x, it is recommended to use Java 17. - - If you feel like you must use Java 1.8, it's strongly suggested to use only the latest version 1.8.0_x. + - The current recommended version of Java is version 17. Even if you are using jars and other plugins that were compiled with Java 1.8.x, or older, it is recommended to use Java 17. + - If you feel like you must use Java 1.8, it's strongly suggested to use only the latest version 1.8.0_x since there are still current security releases. -* You can download it from [Sun SE Development Kit 8]https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html) for product that you need. +* You can download it from [Sun SE Development Kit 8]https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html) for a product that you need. * You can also use Open JDK if Sun's license does not fit your needs. [OpenJDK Install](https://openjdk.java.net/install/) @@ -61,6 +61,7 @@ there are many good resources out there. java -jar BuildTools.jar --rev 1.17.1 java -jar BuildTools.jar --rev 1.18.2 java -jar BuildTools.jar --rev 1.19.3 + java -jar BuildTools.jar --rev 1.20.1 ``` * For example, with BuildTools.jar being in a root directory, create a subdirectory and then start a build within that directory. The benefit is that you can use the same BuildTools.jar to build multiple different versions of spigot. This example starts off with building a v1.17.1 instance and then builds a 1.8.8 instance. Normally you wouldn't build multiple versions of spigot, but this shows how easy and flexible it is to build any version of spigot that has been released. @@ -79,7 +80,7 @@ there are many good resources out there. * **Updating BuildTools:** Once in a while you will be prompted to update the BuildTools.jar file. To do update it, all you need to do is to just download it, and replace the older one you were using. -* **Updating the built servers:** Every once in a while, when you are starting a server, there may be a notification that the server software needs to be update. Just rerun the BuildTools for the same version within the original build directory. The build tools will update all of the changed resources and then generate the new server jars that you copy to the actual server (see the next step). +* **Updating the built servers:** Every once in a while, when you are starting a server, there may be a notification that the server software needs to be update and the server startup will be paused for about 20 seconds. Just rerun the BuildTools for the same version within the original build directory. The build tools will update all of the changed resources and then generate the new server jars that you copy to the actual server (see the next step).
diff --git a/docs/prison_docs_012_setting_up_prison_basics.md b/docs/prison_docs_012_setting_up_prison_basics.md index 0dee13510..71d18ace3 100644 --- a/docs/prison_docs_012_setting_up_prison_basics.md +++ b/docs/prison_docs_012_setting_up_prison_basics.md @@ -7,7 +7,7 @@ This document provides a quick overview on how to install Prison and get it running. -*Documented updated: 2023-01-28* +*Documented updated: 2023-07-24*
@@ -18,9 +18,10 @@ This document provides a quick overview on how to install Prison and get it runn Download Prison from one of the following sites: * [spigotmc.org's Prison History Page](https://www.spigotmc.org/resources/prison.1223/history). -* [Polymart.org](https://polymart.org/resource/prison-1-8-x-1-17.678) +* [Polymart.org](https://polymart.org/resource/prison-1-8-x-1-20-x.678) * [bukkit.org](https://www.curseforge.com/minecraft/bukkit-plugins/mc-prison-v3) +These sites will have stable alpha releases published to them from time to time. Setting up Prison is simple: @@ -34,7 +35,7 @@ Setting up Prison is simple: - 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 the prison jar file to your server's plugin directory. +* Copy the prison jar file to your server's `/plugin` directory. * Remove any older prison jar file @@ -43,7 +44,7 @@ Setting up Prison is simple: * 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. -* It is strongly suggested that `/ranks autoConfigure` is ran to initially setup your Prison environment. A great deal of configurations are setup that can save a lot of effort. Even if you are wanting to start from scratch, it may be worth giving it a try to see how some of the more complex settings are configured. You can always start over by deleting the `plugins/Prison/` directory. +* It is strongly suggested that `/ranks autoConfigure` is ran to initially setup your Prison environment. A great deal of configurations are setup that can save a lot of effort. Even if you are wanting to start from scratch, it may be worth giving it a try to see how some of the more complex settings are configured. You can always start over by deleting the `/plugins/Prison/` directory then restarting the server. * Follow Prison's documentation on customization; at this point it's ready for use. @@ -60,7 +61,7 @@ Setting up Prison is simple: There may be no hard dependencies that will prevent Prison from running, but there are some core plugins that will make it easier to use, and are even required for activation of some features within Prison. This short list is just a suggestion, but alternatives do exist and may be outside of our ability to comment or assist in their usage. -* **Vault** - Optional, but STRONGLY Suggested - This is perhaps the most important plugin. This plugin provides a common way to access other plugins running on your server, but without having to write any code within Prison to support them. Vault provides the mapping of a plugin's unique APIs to a common Vault API. Vault helps support Economy, Permissions, and Placeholders. Because of Vault, Prison can work flawlessly with dozens of other plugins. Please refer to Vault's documentation for what it supports. +* **Vault** - Optional, but **STRONGLY Suggested** - This is perhaps the most important plugin. This plugin provides a common way to access other plugins running on your server, but without having to write any code within Prison to support them. Vault provides the mapping of a plugin's unique APIs to a common Vault API. Vault helps support Economy, Permissions, and Placeholders. Because of Vault, Prison can work flawlessly with dozens of other plugins. Please refer to Vault's documentation for what it supports. Valut does have it's limitations, such as it can only support one currency at a time. * **EssentialsX** - **STRONGLY SUGGESTED**, but still Optional - Provides many of the basic commands and behaviors that you would expect from a Spigot server such as chat, warps, and even some moderation commands and commands that can be given to premium players. EssentialsX is not Essentials, since Essentials is an older abandoned project, and EssentialsX is a forked project that is still maintained. Unfortunately, internally it is identified as simply Essentials, but you can tell it's EssentialsX if the version is greater than 2.15.x. @@ -72,6 +73,8 @@ There may be no hard dependencies that will prevent Prison from running, but the Prison requires an active economy in order to active the Ranks plugin. When Prison starts up, it performs many validations on the mines and ranks as they are being loaded. With Ranks, if Prison cannot find an active economy, then it will refuse to load the Ranks module due to possible server corruption (ie... what failed that there is no economy). +We say an economy is required, but it's still optional. Without an economy, you cannot use the ranks module, but we fully understand that some servers choose to use a different ranks plugin. + * **EssentialsX Economy** - SUGGESTED - Optional - This is a simple economy plugin that just works well. If you don't have a specific need to use another economy plugin, then it may be best to use this one since it works so well. The reason why we recommend this economy is because it always works. That said, we acknowledge the reason it works well, is because it is so simple, so if there are features in other economy plugins that you want to use on your sever, then please explore using them. But overall, if you just want an economy that is rock solid, then EssentialsX's Economy is a great choice. @@ -163,13 +166,15 @@ All of Prison's placeholders have an alias. An alias is a shortened name for a **NOTE: Prison no longer supports MVdWPlaceholder** because it could not support all of the advanced features with placeholders that prison uses. Also, since prison generates so many possible placeholders, MVdW pollutes the console log with thousands of lines of useless information stating each variant of a placeholder has been registered. We also dropped support for this plugin because there is no way to contact the developer because they hide behind a pay-wall, and I'm not about to buy one of their other plugins to just tell them their so-called-free plugin is not working properly. -But perhaps the biggest reason why I dropped support for MVdW is because it's 100% pointless. **PlaceholderAPI** works flawlessly with MVdW so there is absolutely no reason why prison needs to support MVdW anymore. If you need to use MVdW, then please keep using it, it works great with their other plugins. But you can use PlaceholderAPI along with it too. So there are zero reasons why you cannot use PlaceholderAPI, and everyone is happy. +But perhaps the biggest reason why I dropped support for MVdW is because it's 100% pointless from Prison's perspective. **PlaceholderAPI** works flawlessly with MVdW installed too, so there is absolutely no reason why prison needs to support MVdW anymore since everything works perfectly through PlaceholderAPI. If you need to use MVdW, then please keep using it, it works great with their other plugins. But you can use PlaceholderAPI along with it too. So there are zero reasons why you cannot use PlaceholderAPI, and everyone is happy. ~~Suggested to Avoid - Prison does support this plugin, but since it is used mostly with premium plugins, we have no way to fully test this plugin to ensure it actually works correctly. We've heard very few people have used this plugin, but we've heard it does work well. Use at your own risk.~~ ~~With this plugin, all placeholders are registered with it automatically when prison starts up, and all placeholders should be used as all lower case. Because prison has so many placeholders, with many that are expanded based upon ladders, ranks, and mine names, a modest prison server could generate and register well over 1000 placeholders. MVdWPlaceholder appears to be very verbose so you will see a lot of logging in the console when it starts up.~~ -~~It should also be noted that because of some of the limitations of MVdW, not all features of Prison's placeholder support will be supported. For example, you may not be able to reload placeholders, or use placeholder attributes to customize how placeholders are used.~~ +~~It should also be noted that because of some of the limitations of MVdW, not all features of Prison's placeholder support will be supported. For example, you may not be able to reload placeholders, or use placeholder attributes to customize how placeholders are used. Also the numerical sequence placeholders may not work either.~~ + +~~Like it was said earlier, there is no way to contact the developers. If we could make just one suggestion, and that would be to allow setting up placeholders by specifying a prefix that's used. This is how PlaceholderAPI works, so with just registering once, a value of "prison_" that ensures all of prison's placeholders are routed to us. Also, make sure the allowable placeholders are not limited by length. Prison use placeholder attributes that can customize how the results are modified which gives an almost limitless opportunity to customize placeholders as desired to match the server's design standards. The third suggestion for changes is to allow the reloading of placeholders with a simple command, such as reregistering them. As admins add ranks, ladders, or mines, or even change their names, then all of the placeholders must be reregistered so the new entries are included.~~ @@ -243,7 +248,9 @@ Warning: People have paid for this plugin only to find out after the fact that i If you purchase this plugin to use on your server, do so with great caution since it is not supported and it may not integrate with prison. [ * Not supported * Tokens * Not supported * ](https://www.spigotmc.org/resources/%E2%9A%A1%EF%B8%8F-tokens-%E2%9A%A1%EF%B8%8F-40-enchantments-%E2%AD%95-free-expansions-%E2%AD%95-25-off.79668/) -**Please Note:** There is another plugin by the same name "Tokens" that strictly deals with tokens and not enchantments, which works just fine with prison. + +**Please Note:** There is another plugin by the same name "Tokens" that strictly deals with tokens and not enchantments, which works just fine with prison. I have even personally contributed to that plugin to provide caching of the player's data to resolve an issue with ultra fast mining in prison. Basically it used to be that if you give players tokens too quickly, it would lockup the server trying to update the save files. Now it easily supports 100's, if not 1000's of transactions per second without any impact to the TPS. + ### Enchantment Plugin Features Supported @@ -461,15 +468,16 @@ Once entered, it will enable the following submit tools: `/prison support submit` - Show the available tools. ``` +/prison support submit version /prison support submit configs /prison support submit latestLogs /prison support submit mines /prison support submit ranks -/prison support submit version ``` -Here is an example that I generated from one of my test servers on 2021-12-03. I have no idea how long the content remains available, but for support purposes, we only need this information for a few hours. - [https://paste.helpch.at/itejovejeh](https://paste.helpch.at/itejovejeh) +Here is an example that I generated from one of my test servers on 2021-12-03. I have no idea how long the content remains available, but for support purposes, we only need this information for a few hours. It appears like this information is never deleted? As such, here are two different versions which shows you how much more information has been addeed. + [https://paste.helpch.at/silihuxaja](https://paste.helpch.at/silihuxaja) From Prison v3.3.0-alpha.15a + [https://paste.helpch.at/itejovejeh](https://paste.helpch.at/itejovejeh) From Prison v3.2.11-alpha.9 # Prison Commands diff --git a/docs/prison_docs_013_Prison_Help.md b/docs/prison_docs_013_Prison_Help.md index f6d6bd04e..353dfa148 100644 --- a/docs/prison_docs_013_Prison_Help.md +++ b/docs/prison_docs_013_Prison_Help.md @@ -13,6 +13,10 @@ This document provides some important information on how to find help in setting # Overview +We take support seriously. We realize that being a Prison plugin, we are working with a lot of different aspects of minecraft, and that there are many other plugins that may cross paths with Prison. We cannot support every single plugin out there, but we will try to resolve and identify all problems that are brought to our attention.. + +Because we are so very concerned with your server's functionality, we have put a lot of effort in trying to create support tools to better understand what is happening. We cannot control other plugins, but prison is capable of tracking and reporting many fine-grained details about how it works and what is happening step-by-step. This can allow us to figure out difficult problems. + If you are having problem, please take a quick look at the following documents as found in the Table of Contents: * Setting up prison and various plugins - If special conditions for their configurations become apparent in order for prison to work, notes will be added there. If you notice there is a special configuration consideration that we did not document, please share with us so we can update the documents. @@ -129,6 +133,77 @@ You can also submit a help ticket on the Prison github Issues tab, but the respo + +# Prison Support Submit Information + +Prison now has a built in way to share your configurations and settings with support personnel. + +More information will be documented in the future, but for now, here are the basics on how to use it. + +When requested by the Prison support team, you would first enter the following command to set your name that will be included on all reports to help identify who the are related to. It doesn't have to be your full discord name, but enough characters to allow us to identify who you are. + + +These commands will collect all of the related information from your Prison setup, and send it to the website `https://paste.helpch.at`. It will provide you with an URL. All you need to do is to copy and paste that URL in to the discord chat so the Prison support team can help with your issue. + + +`/prison support setSupportName ` + +Once entered, it will enable the following submit tools: + +`/prison support submit` - Show the available tools. + +``` +/prison support submit version +/prison support submit ranks +/prison support submit mines +/prison support submit configs +/prison support submit listeners +/prison support submit latestLogs +``` + +**Version** This is generally the most requested information needed for support. Provides general overall information on Prison and it's environment on the server. This is similar to the command `/prison version all` plus a few other features such as listeners, and the command cache. + +**Ranks** This is everything related to ranks. Includes ladders, ranks lists, and rank details. It also includes all of the raw save file for these items too. + +**Mines** This is everything related to mines. Includes the mine list, mine info, and the related files for each mine. + +**Configs** These are all of the other config files that are within prison. These do not include any of the files included in ranks or mines. + +**Listeners** These are dumps of the event listeners for BlockBreak, chat, and playerinteract. See the command `/prison support listeners help` for more detailed information. + +**LatestLogs** This will send the latest log file, up to a max allowed amount. + + +Here are two examples that I generated from one of my test servers on 2021-12-03 and 2023-07-24. I have no idea how long the content remains available, but for support purposes, we only need this information for a few hours. It appears like this information is never deleted? As such, here are two different versions which shows you how much more information has been added. + [https://paste.helpch.at/silihuxaja](https://paste.helpch.at/silihuxaja) From Prison v3.3.0-alpha.15a + [https://paste.helpch.at/itejovejeh](https://paste.helpch.at/itejovejeh) From Prison v3.2.11-alpha.9 + + +# Prison Support HTML Output Files + +As a brand new feature, Prison now is able to generate HTML files that are stored within the `plugins/Prison/backups/` directory. It includes information from version, ranks, mines, listeners, and configs. See above. The nice thing about this support format is that it reproduces all of the colors as found in the console version of these commands. + +This file format is also good for server owners who do not want to post their server information on another website. + +To generate the file, use the command: +`/prison support saveToFile help` + +To generate with the defaults settings: +`/prison support saveToFile basic` + +If an existing file exists, it will generate the next one in the series. When ran, it will identify what the current file is. Please send this file to support. + + + +If you want to use this format instead of the above file that are sent to paste.helpch.at, then generate the file and you can DM it to either Blue or Madog. It's best to ask before sending to confirm we are available to respond to your needs. + + +NOTE: Hyperlinks and table of contents will be added to this HTML support document. + + +
+ + # Prison Debugger diff --git a/docs/prison_docs_100_setting_up_auto_configure.md b/docs/prison_docs_100_setting_up_auto_configure.md index e267ba0ed..9e5fc2b5b 100644 --- a/docs/prison_docs_100_setting_up_auto_configure.md +++ b/docs/prison_docs_100_setting_up_auto_configure.md @@ -10,7 +10,7 @@ This document provides information on how to get started quickly using Prison's [Prison Log File Examples - Starting Prison & auto configure](prison_docs_101_auto_configure_log_examples.md) -*Documented updated: 2021-12-11* +*Documented updated: 2023-09-09*
@@ -19,6 +19,10 @@ This document provides information on how to get started quickly using Prison's This document covers how to run `/ranks autoConfigure`, it's options, and what to do after the command runs. +It is strongly suggested to run this command and read the current help documentation for the command because a lot of changes have been happening to the commands, but these documents may be out of date: +`/ranks autoConfigure help` + + Prison's Auto Configure will perform most of the basic configurations to get you up and running quickly. This feature will perform the following tasks for you: @@ -38,7 +42,7 @@ Prison's Auto Configure will perform most of the basic configurations to get you * Auto assign random Mine Liners to each mine. -* Auto generate 10 Prestige Ranks and have them enabled by default. +* Auto generate 25 Prestige Ranks and have them enabled by default. * Enable Ladder Base Rank Cost Multiplier for the Prestiges ladder. Once a player prestiges, this will enable a rank cost multiplier that will increase all rank cost. As the player ranks upon the prestiges ladder, the rank costs will increase. @@ -311,13 +315,40 @@ Generally you would never need to use any of the options. But they do provide f * **mult=x** - The default value for the multiplier is 1.5. This is the multiplier that is used calculate the next rank. So if the first rank has an initial cost of 50,000 then the second rank cost is 1.5 times that value. Therefore the second rank will have a cost of 75,000 (50,000 * 1.5). -* **Force** - If any mines or ranks exist, normally it will prevent auto configure from running. **Force** forces it to run, but with consequences. It will skip over any rank or mine that it would otherwise try to generate. It will not add rank commands to existing ranks. It will not add blocks to existing mines. It will not hook up ranks to mines. Nor will it configure such features as Mine Access Permissions. If you decide to use **force** you do so at your own risks. +* **Force** - If any mines or ranks exist, normally it will prevent auto configure from running. **Force** forces it to run, but with consequences. Auto configure will try to merge any preexisting ranks and mines, but it will also replace all blocks in all mines. There maybe some unexpected consequences to forcing an auto configure, so back up your data. If you decide to use **force** you do so at your own risks. + + +* **forceKeepBlocks** - If forcing auto configure to run again, the 'forceKeepBlocks' will prevent existing mines from having their blocks reset to the defaults. + + +* **ranks** - If specified, it will only generate ranks and not the mines or prestigies. + + +* **mines** - If specified, it will only generate mines and not the ranks or prestiges. + +* **prestiges** - If specified, it will only generate prestiges and not the mines or ranks. + + +* **prestiges=x** - Will set how many initial prestige ranks to create. + +* **prestigeCost=x** - Sets the initial cost for P1; default value is 1_000_000_000. + +* **prestigeMult=x** - Is an additional multiplier for presetige ranks, with the default value of 1. The cost for each prestige rank is based upon the initial presetigeCost, times the prestige level so p3 will be 3 times the cost of p1 with the prestige multiplier will multiplied against that value. So for default values with a 1.75 multiplier p3 cost = 1_000_000_000 * 3 * 1.75. Default values [full price=50000 mult=1.5 prestiges=25 presetigeCost=1000000000 prestigeMult=1] + +* NOTE: Use of these parameters, you can adjust some of the settings on your server, without replacing preexisting configurations. + + +Other commands of interest: +* `/ranks ladder rankCostMultiplier help' - Is used to calculate a player's rank cost when they rankup. This is a multiplier based up a ladder, where the ladder's multiplier is multiplied by that ladder's position. So if a prestige ladder uses a rank cost multiplier of 0.1 (10 percent), then when a player is at P0 (no presetige rank) it will not increase the costs of the default ranks prices. But when they are at P1, then it will be a 10% increase, and at p10 it will be at a 100% increase (twice as expensive than p0). A ladder could be set to zero so it does not contribute to the player's total calculated rank cost multipliers. -* **ranks** - If specified, it will only generate ranks and not the mines. +* `/ranks ladder applyRankCostMultiplier help' - This is a ladder setting where if a ladder applies the player's rank cost multiplier then it's rankup costs on it's ladder will apply the rank cost multiplier. If the ladder is disabled, then it will use the raw rank cost. Note a ladder can be disabled, but yet still contribute to the players total rank cost multiplier. +* `/ranks ladder resetRankCosts help' - This resets all rank costs on a ladder based upon a uniform formula. This is good to use after adding new ranks, and you want each rank to be progressivly more expensive, at a uniform rate. -* **mines** - If specified, it will only generate mines and not the ranks. +* '/sellall multiplier addLadder help' - Adds one multiplier per rank for a given ladder. You can control how the multiplier is generated per rank. +* '/sellall multiplier deleteLadder help' - Deletes all multipliers for a given ladder. This is very useful when adding adding new multipliers by ladder. +* '/sellall multiplier list help' - can limit the list of multipliers by ladder and can control how many columns are in the display. @@ -386,7 +417,8 @@ The other method is a little more controlled, and that's using prison wand to se Prison has an advanced command handler that is able to do a lot of things. One of it's features is to provide more information on each command that it has registered. To activate this feature, just add the keyword `help` to the end of any command. Here are a few examples. ``` -/mines info help +/ranks autoconfigure help +/mines info help /ranks promote help /ranks command add help /prison support submit diff --git a/docs/prison_docs_101_setting_up_mines.md b/docs/prison_docs_101_setting_up_mines.md index e116ed6db..15594f294 100644 --- a/docs/prison_docs_101_setting_up_mines.md +++ b/docs/prison_docs_101_setting_up_mines.md @@ -15,6 +15,9 @@ This document provides some highlights to how to setup mines. It is a work in p This document should be able to provide the basic information to get your mines configured. There are many options available within Prison, and also through the use of other plugins, so advanced topics that blend multiple plugins, and their various settings, are beyond the scope of this document. +As a side note, if you installed prison, and it appears like it may not be working in a specific world, please see the `config.yml` file to see if prison's command handler is disabled within that world. If it is, then all prison commands will be turned off in that world, and there will be no way to bypass it unless the config.yml file is changed. + + Prison has a list of suggested plugins that works well with Prison, and a few that do not work at all with Prison. Please see the following document for a list of suggested plugins. If you have a favorite plugin that works well with Prison and it's not in that list, then please reach out to us in our discord server and make a suggestion for it to be added. [Setting up Prison - The Basics](prison_docs_012_setting_up_prison_basics.md) @@ -249,7 +252,11 @@ Some of the highlights of these commands are as follows: * `/mines set liner` : A quick way to wrap your mine with a 2D Pattern in 3D space. This command also will `repair` the area around a mine, and will effectively erase a liner. There are six directions that can be specified for change: `north`, `south`, `east`, `west`, `top`, and `bottom`. `walls` also is a shortcut for `north`, `south`, `east`, and `west`. The patterns available are listed by the command. There is even a `force` setting that will allow the mine to be wrapped when in air, since the wrappings normally needs blocks in contact with the mine so it is able to conform to the terrain. + + * `/mines set mineSweeper` : If all else fails to get Prison to monitor and track blocks that are broken within a mine, mostly due to conflicts with other plugins, then this option can provide a last chance effort to monitor the progress within a mine. It is very rare that you would have to use this setting and the chances are that there are better ways to get the mines working correctly. The larger the mine, the more costly this setting is to enable. + + * **Removed:** `/mines set move` is a new command that is not yet enabled. It is still in development, but will be active soon. This command will move a whole mine as a single unit, be it a few blocks or many (not recommended). The same effect of moving a mine can be done through the command: `/mine set size` but note it will possibly damage or destory the surrounding builds if not careful. * **Removed:** `/mines set norank` : Disconnect the mine from a rank. **Note:** This command has been changed to `/mines set rank *none*` to delete the rank from the mine. @@ -266,7 +273,11 @@ Some of the highlights of these commands are as follows: * `/mines set sortOrder` : Mines can be sorted for view within `/mines list` or the GUI. Setting the sortOrder allows you manually set the order in which the mines are listed. There is even the option to suppress (hide) mines from that list too by setting the sort order to a -1. * `/mines set spawn` : Sets the mines spawn point. Whatever you are looking at is what the players will be looking at when they tp to that spot. * `/mines set tag` : Set a mine tag value that can be used with placeholders. -* `/mines set tracer` : Removes all blocks in a mine and replaces them with air, with the exception of the corners, of which are replace with pink_stained_glass. This function allows for easy viewing of the full mine without the blocks getting in the way. It also helps when setting the liner of the mine. Using `/mines reset` returns the mine to normal functionality, or it will reset on its own. + + +* `/mines set tracer help` : Removes all blocks in a mine and replaces them with air. This is good to allow you to access and work on the liners or ladders. There are three options with this command: `outline`, `corners` and `clear`. The option `outline` is the default and will use this option unless the others are specified. `outline` will apply pink glass blocks along the outline of the mine. `corners` will only place pink stained glass blocks in the 8 corners of the mine. And `clear` will add no tracers and will result in a fully cleared mine. This function allows for easy viewing of the full mine without the blocks getting in the way. It also helps when setting the liner of the mine. Using `/mines reset` returns the mine to normal functionality, or it will reset on its own. + +. * `/mines set zeroBlockResetDelay` : If the mine runs out of blocks, when enabled, it will force a manual reset after the specified delay. The delay can be zero for instant reset. diff --git a/docs/prison_docs_111_mine_commands.md b/docs/prison_docs_111_mine_commands.md index 6f11fbc15..346b73749 100644 --- a/docs/prison_docs_111_mine_commands.md +++ b/docs/prison_docs_111_mine_commands.md @@ -29,7 +29,7 @@ My personal goals to use this new feature was to dynamically build a large fores The family of mine commands are as follows: ``` -/mines command +/mines ``` Mine Commands diff --git a/docs/prison_docs_310_guide_placeholders.md b/docs/prison_docs_310_guide_placeholders.md index 1d9b8707e..0dd29d5ca 100644 --- a/docs/prison_docs_310_guide_placeholders.md +++ b/docs/prison_docs_310_guide_placeholders.md @@ -7,7 +7,7 @@ This document covers different aspects of placeholders within Prison. It explains how they work, how to use them, and different ways to use them. -*Documented updated: 2022-08-14* +*Documented updated: 2023-10-01*
@@ -59,8 +59,13 @@ Sub-command listing of all placeholders commands: * **/prison placeholders stats** -> A new command that currently only shows what placeholders have been hitting prison and their total hit count and the total average duration to process. This tool provides a simple pre-cache to more quickly identify which is the correct placeholder to use with the raw placeholder text. This even include bad placeholder hits so the pre-cache can bypass processing of the junk, which improves server performance. Eventually this will also include a placeholder value cache. +> A new command that currently only shows what placeholders have been hitting prison and their total hit count and the total average duration to process. This tool provides a simple pre-cache to more quickly identify which is the correct placeholder to use with the raw placeholder text. This even includes bad placeholder hits so the pre-cache can bypass processing of the junk, which improves server performance. Eventually this will also include a placeholder value cache. +> The placeholder cache helps reduce the cost of resolving the correct placeholder. + +> To clear and reset the placeholder cache, use the command `/prison placeholders stats resetCache`. + +> NOTE: Viewing and resetting the placeholder cache/stats is a good way to debug possible placeholder problems. This can confirm if prison is getting requests for the given placeholder, or if a placeholder that you're using is bad or incorrect. * **/prison placeholders reload** @@ -219,6 +224,8 @@ There are actually two major kinds of player based placeholders; a third type is The other player based placeholders, which complements the Rank Placeholders, are the ladder placeholders that narrows the ranks down to a specific ladder. So with our example above, if you only want the ranks from the *default* ladder, that is now possible. Also you can control the order they appear by ordering the ladder placeholders in a specific sequence. +NOTE: Player based placeholders can now be used with non-player placeholders by using a placeholder attribute's `player=` attribute. + The Mine based placeholders provide details about mines, and the mine name becomes part of the placeholder name. Out of all of the possible mine based placeholders, each one is duplicated for each mine. So, in rough terms, if there are different mine placeholders and you have 40 mines, then prison will generate about 400 place holders: 40 mines x 10 placeholders each = 400 placeholders for prison. The same applies to the ladder placeholders as the mine placeholders; for every ladder, there will be a specific placeholder that represents each ladder. @@ -245,6 +252,9 @@ Placeholders within prison can now be dynamically customized without having to m The **Placeholder Attributes** is additional text that is added at the end of a placeholder but within the escape characters. The placeholder attribute always begins with a double colon `::` and each parameter is separated with a single colon `:`. Some placeholders cannot use the attributes, and not all attributes can be used on a placeholder. See additional information below that pertains to each attribute. +**Player based placeholders** require player based requests that includes the player. Plugins that provide player based context would be like chat prefixes, scoreboards, and other placeholder consumers that need to use the player based placeholders. Some examples of placeholder consumers that will not have player based contexts, are with scoreboards and some script environments; these requests for player based placeholders would normally fail under regular conditions. To use player based placeholders with plugins that cannot support the player, you can solve this issue with the use of placeholder attributes with the **player=<playerName>** attribute. See notes below on all placeholder attribute types. + + As of v3.3.0-alpha.11h one placeholder can have more than one Placeholder Attribute, but they have to be of a different type. At this time, this really is not beneficial since the Placeholder Attributes are specific to a certain type of data. But this opens the door to future possibilities that are not possible currently, such as hybrid between a bar graph with a value super-imposed on top of it. @@ -276,6 +286,12 @@ A few Examples using Placeholder Attributes: * **OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOxxxxxxxx** +* `{prison_rank_tag::text:player=RoyalBlueRanger}` - When used in non-player supported plugins, such as holographic displays, this will enable the use of player-based placeholders for the specified player. + + +* `{prison_rankup_cost_remaining_formatted::nFormat:player=RoyalBlueRanger}` - When used in non-player supported plugins, such as holographic displays, this will enable the use of player-based placeholders for the specified player. + + The examples above don't show the color for the bar graphs, but here is a screen print that uses a prison command to test the placeholders dynamically within prison: @@ -305,13 +321,14 @@ The Numeric Format attribute will only work on placeholders that return plain nu Example of this attribute's usage is as follows, using descriptions for each parameter. -`::nFormat:format:spaces:unitType:hex:hex2:debug` +`::nFormat:format:spaces:unitType:hex:hex2:debug:player=` - **nFormat**: the keyword to identify this attribute. - **format**: formatting based upon Java's DecimalFormat class. - **Required.** Defaults to #,##0.00. + **Required.** Defaults to #,##0.00. Examples of + how the formatting can be used: * #,### * #,###.00 * #,###.00000 @@ -334,7 +351,7 @@ Example of this attribute's usage is as follows, using descriptions for each par KB, MB, GB, TB, PB, EB, ZB, and YB. * *Note:* Other unitTypes can be added along with different style of - reducers. + reducers. Contact support for these requests. - **hex**: **Optional.** Case sensitive. Non-positional; can be placed anywhere. Only valid value is "hex". When enabled it will translate @@ -352,7 +369,10 @@ Example of this attribute's usage is as follows, using descriptions for each par will log to the console the status of this attribute, along with any error messages that may occur when applying the attribute. - +- **player=<playerName>**: **Optional.** Case insensitive. Non-positional; can be + placed anywhere. If provided, it will try to use the specified + player as the primary player for the placeholder. If the current + user is provided, then this parameter may be ignored. @@ -385,7 +405,7 @@ The bar placeholder attribute only works with placeholders with the word bar in Example of this attribute's usage is as follows, using descriptions for each parameter. -`::bar:size:posColor:posSeg:negColor:negSeg:reverse:hex:hex2:debug` +`::bar:size:posColor:posSeg:negColor:negSeg:reverse:hex:hex2:debug:player=` @@ -420,6 +440,11 @@ Example of this attribute's usage is as follows, using descriptions for each par Only valid value is "debug". When enabled it will log to the console the status of this attribute, along with any error messages that may occur when applying the attribute. + +- **player=<playerName>**: **Optional.** Case insensitive. Non-positional; can be + placed anywhere. If provided, it will try to use the specified + player as the primary player for the placeholder. If the current + user is provided, then this parameter may be ignored. @@ -464,7 +489,7 @@ placeholders. Example of this attribute's usage is as follows, using descriptions for each parameter. -`::text:hex:hex2:debug` +`::text:hex:hex2:debug:player=` @@ -483,6 +508,11 @@ Example of this attribute's usage is as follows, using descriptions for each par Only valid value is "debug". When enabled it will log to the console the status of this attribute, along with any error messages that may occur when applying the attribute. + +- **player=<playerName>**: **Optional.** Case insensitive. Non-positional; can be + placed anywhere. If provided, it will try to use the specified + player as the primary player for the placeholder. If the current + user is provided, then this parameter may be ignored. diff --git a/docs/prison_docs_311_guide_automanager.md b/docs/prison_docs_311_guide_automanager.md index 3cbe8227f..78c9e2404 100644 --- a/docs/prison_docs_311_guide_automanager.md +++ b/docs/prison_docs_311_guide_automanager.md @@ -466,6 +466,45 @@ Remember that the settings for `fortuneBukkitDropsMultiplier`, `fortuneMultiplie * Formula: raw_adjusted_drops x +**Prison's Percent Gradient Fortune Calculation** + +New as of v3.3.0-alpha.15e + +This is a new fortune calculation type, which defines a max fortune amount, and a max bonus payout that is possible. Then based upon the fortune level on the player's tool, it will payout a linear maximum amount, adjusted by a random range. + +To enable, you need to setup the following settings within the autoFeaturesConfig.yml file. If you just upgraded prison, restart prison, and the new settings will be injected in to the config file for you. Then modify those settings, and then use `/prison reload autoFeatures`. + +These settings must be set to these values to use this new fortune calculation: + +```yml + + fortuneFeature: + isCalculateFortuneEnabled: true + isExtendBukkitFortuneCalculationsEnabled: false + isCalculateAltFortuneEnabled: false + percentGradientFortune: + isPercentGradientFortuneEnabled: true + + percentGradientFortuneMaxFortuneLevel: 1000 + percentGradientFortuneMaxBonusBlocks: 200 + percentGradientFortuneMinPercentRandomness: 25.0 +``` + +The last three listed settings can be customized however you need them to be. + + +Percent Gradient Fortune is an alternative fortune calculation that will only be enabled if extendedBukkitFortune and altFortune is turned off. + +Percent Gradient Fortune will always drop a minimum of 1 block with fortune 0 and higher. The max it will ever drop, will be 1 + MaxBonusBlocks-amount. The calculation of the MaxBonusBlocks will be a random roll resulting in 0 bonus blocks, to the MaxBonusBlocks amount IF the player has the max fortune on their tool. + +For fortune amounts less than the maxFortuneLevel, it will be treated as a linear percentage gradient of the max amount. For example, MaxFortuneLevel= 1000, and MaxBonusBlocks= 200. Therefore if the player has a fortune 500, the max bonus they could get would be only 100 blocks, but could be as low as zero bonus blocks since it's a random roll on each calculation. If they have a fort 250, then it will be 25% of 200, or 50 blocks as a max bonus. + +For better control of the randomness applied to the bonus block calculations, the MinPercentRandomness sets the lowest range for the randomness. What this means, is for a maxFortuneLevel= 1000 and a maxBonusBlocks of= 200, and a tool with fort 500, the calcs would be for a bonus between '0' and (500 / 1000 * 200 =) 100 bonus blocks. But with the minPercentRandomness= 25, then the range would be '25%' to 100% of the 100 bonus blocks. The minePercentRandomness would ensure a higher payout of bonus blocks, without effecting the max payout. minPercentRandomness has a valid range of 0.0 (off) to 99.0 percent. + +No other fortune multipliers will apply to these calculations. + +The percentage gradient is a very controlled way of paying out fortune bonuses. +
diff --git a/gradle.properties b/gradle.properties index 1e461305f..01d7ea2a1 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.3.0-alpha.15 +version=3.3.0-alpha.16 diff --git a/gradlew8.bat b/gradlew8.bat index 009240f46..7230d4d90 100644 --- a/gradlew8.bat +++ b/gradlew8.bat @@ -1 +1 @@ -./gradlew build -Dorg.gradle.java.home="C:\Program Files\Java\jdk1.8.0_321" --stacktrace \ No newline at end of file +./gradlew build -Dorg.gradle.java.home="C:\Program Files\Java\jdk1.8.0_321" --stacktrace %* \ No newline at end of file diff --git a/prison-core/build.gradle b/prison-core/build.gradle index d158f866a..8c84bad53 100644 --- a/prison-core/build.gradle +++ b/prison-core/build.gradle @@ -25,10 +25,21 @@ compileTestJava.options.encoding = "UTF-8" repositories { mavenCentral() + + //maven { url = "https://jitpack.io" } } dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' + + //implementation 'com.github.InstantlyMoist:privatebin-java-api:1.0.2' + + //implementation 'org.json:json:20230227' + + implementation fileTree(dir: 'lib', + include: ['privatebin-java-api-1.0.2.jar', + 'json-20230227.jar']) + } /* @@ -46,7 +57,15 @@ shadowJar { // https://mvnrepository.com/artifact/com.google.code.gson/gson include(dependency('com.google.code.gson:gson:2.10.1')) //include(dependency('com.google.code.gson:gson:2.8.6')) + + include(dependency('org.json:json:20230227')) + include(dependency('com.github.InstantlyMoist:privatebin-java-api:*')) } + + relocate 'org.json', 'tech.mcprison.prison.orgjson' + relocate 'com.github.InstantlyMoist', 'tech.mcprison.prison.privatebin8' + + classifier 'API' archiveVersion = null } diff --git a/prison-core/lib/json-20230227.jar b/prison-core/lib/json-20230227.jar new file mode 100644 index 000000000..abdb16b76 Binary files /dev/null and b/prison-core/lib/json-20230227.jar differ diff --git a/prison-core/lib/privatebin-java-api-1.0.2.jar b/prison-core/lib/privatebin-java-api-1.0.2.jar new file mode 100644 index 000000000..037b7b22e Binary files /dev/null and b/prison-core/lib/privatebin-java-api-1.0.2.jar differ 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 6598e41b4..fe810f237 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -43,6 +43,7 @@ import tech.mcprison.prison.commands.RegisteredCommand; import tech.mcprison.prison.commands.Wildcard; import tech.mcprison.prison.discord.PrisonPasteChat; +import tech.mcprison.prison.discord.PrisonSupportFiles; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.localization.LocaleManager; @@ -73,6 +74,7 @@ public class PrisonCommand private List prisonStartupDetails; private String supportName = null; + private PrisonSupportFiles supportFile = null; private TreeMap supportURLs; @@ -536,7 +538,9 @@ public void troubleshootListCommand(CommandSender sender) { @Command(identifier = "prison placeholders test", - description = "Converts any Prison placeholders in the test string to their values", + description = "Converts any Prison placeholders in the test string to their values. " + + "Use '-s' keyword to reduce output text. " + + "All placeholder attributes are supported.", onlyPlayers = false, permissions = "prison.placeholder") public void placeholdersTestCommand(CommandSender sender, @Arg(name = "playerName", description = "Player name to use with player rank placeholders (optional)", @@ -574,6 +578,10 @@ public void placeholdersTestCommand(CommandSender sender, player = getPlayer( sender ); } + boolean isShort = text.startsWith( "-s " ); + if ( isShort ) { + text = text.substring( 3 ); + } ChatDisplay display = new ChatDisplay("Placeholder Test"); @@ -588,18 +596,18 @@ public void placeholdersTestCommand(CommandSender sender, String translated = Prison.get().getPlatform().getPlaceholders() .placeholderTranslateText( playerUuid, playerName, text ); - builder.add( String.format( "&a Include one or more Prison placeholders with other text...")); - builder.add( String.format( "&a Use { } to escape the placeholders.")); - - // Show player info here like with the search: - if ( player != null ) { - builder.add( String.format( "&a Player: &7%s &aPlayerUuid: &7%s", player.getName(), - (playerUuid == null ? "null" : playerUuid.toString()))); - - } - - - builder.add( String.format( "&7 Original: \\Q%s\\E", text)); + if ( !isShort ) { + builder.add( String.format( "&a Include one or more Prison placeholders with other text...")); + builder.add( String.format( "&a Use { } to escape the placeholders.")); + + // Show player info here like with the search: + if ( player != null ) { + builder.add( String.format( "&a Player: &7%s &aPlayerUuid: &7%s", player.getName(), + (playerUuid == null ? "null" : playerUuid.toString()))); + } + + builder.add( String.format( "&7 Original: \\Q%s\\E", text)); + } builder.add( String.format( "&7 Translated: %s", translated)); @@ -873,24 +881,54 @@ public void reloadAutoFeatures(CommandSender sender ) { sender.sendMessage( filePath ); } catch ( IOException e ) { - // Ingore + // Ignore } - try { +// try { +// +// if ( AutoFeaturesWrapper.getInstance().getBlockConvertersConfig() != null ) { +// +// File bcFile = AutoFeaturesWrapper.getInstance().getBlockConvertersConfig().getConfigFile(); +// if ( bcFile != null && bcFile.exists() ) { +// +// String filePath = bcFile.getCanonicalPath(); +// sender.sendMessage( filePath ); +// } +// } +// +// } +// catch ( IOException e ) { +// // Ignore +// } + } + + + @Command(identifier = "prison reload blockConverters", + description = "BlockConverters reload: Reloads the block converter settings. The current " + + "settings will be discarded before reloading the configuration file.", + onlyPlayers = false, permissions = "prison.autofeatures") + public void reloadBlockConverters(CommandSender sender ) { + + if ( AutoFeaturesWrapper.getBlockConvertersInstance() != null ) { - if ( AutoFeaturesWrapper.getInstance().getBlockConvertersConfig() != null ) { - - File bcFile = AutoFeaturesWrapper.getInstance().getBlockConvertersConfig().getConfigFile(); + AutoFeaturesWrapper.getBlockConvertersInstance().reloadConfig(); + + String message = "&7BlockConverters were reloaded. The new settings are now in effect. "; + sender.sendMessage( message ); + + try { + File bcFile = AutoFeaturesWrapper.getBlockConvertersInstance().getConfigFile(); if ( bcFile != null && bcFile.exists() ) { String filePath = bcFile.getCanonicalPath(); sender.sendMessage( filePath ); } } + catch ( IOException e ) { + // Ignore + } } - catch ( IOException e ) { - // Ingore - } + } @@ -1079,7 +1117,8 @@ public void autoFeaturesInformation(CommandSender sender) { @Command(identifier = "prison debug", description = "Enables debugging and trouble shooting information. " + - "For internal use only. Do not use unless instructed.", + "For internal use only. Do not use unless instructed. This will add a lot of " + + "data to the console.", onlyPlayers = false, permissions = "prison.debug", aliases = {"prison support debug"} ) public void toggleDebug(CommandSender sender, @@ -1087,16 +1126,39 @@ public void toggleDebug(CommandSender sender, @Arg(name = "targets", def = " ", description = "Optional. Enable or disable a debugging target, or set a count down timer. " + "[on, off, targets, (count-down-timer), selective, jarScan, " + - "testPlayerUtil, testLocale, rankup ] " + + "testPlayerUtil, testLocale, rankup, player= ] " + "Use 'targets' to list all available targets. Use 'on' or 'off' to toggle " + "on and off individual targets, or 'all' targets if no target is specified. " + "If any targets are enabled, then debug in general will be enabled. Selective will only " + "activate debug with the specified targets. " + "A positive integer value will enable the count down timer mode to enable " + "debug mode for a number of loggings, then debug mode will be turned off. " + - "jarScan will identify what Java version compiled the class files within the listed jars." + "jarScan will identify what Java version compiled the class files within the listed jars. " + + "If a player name is given, all debug messages that are tracked by player name will only be " + + "logged for that player. Example: `/debug playerName=RoyalBlueRanger 5` will log only " + + "5 debug messages for that player, then debug mode will be disabled. " ) String targets ) { + String playerName = null; + + String playerStr = extractParameter("player=", targets); + if ( playerStr != null ) { + targets = targets.replace( playerStr, "" ); + playerName = playerStr.replace( "player=", "" ).trim(); + + if ( playerName != null ) { + + Output.get().setDebugPlayerName( playerName ); + + sender.sendMessage( "Prison Debug Mode enabled only for player: " + playerName ); + } + else { + Output.get().setDebugPlayerName( null ); + + sender.sendMessage( "Prison Debug Only-for-player Mode has been disabled. Debug mode will be logged for all players." ); + } + } + if ( targets != null && "jarScan".equalsIgnoreCase( targets ) ) { PrisonJarReporter pjr = new PrisonJarReporter(); @@ -1161,6 +1223,27 @@ public void toggleDebug(CommandSender sender, } + + private String extractParameter( String key, String options ) { + return extractParameter( key, options, true ); + } + private String extractParameter( String key, String options, boolean tryLowerCase ) { + String results = null; + int idx = options.indexOf( key ); + if ( idx != -1 ) { + int idxEnd = options.indexOf( " ", idx ); + if ( idxEnd == -1 ) { + idxEnd = options.length(); + } + results = options.substring( idx, idxEnd ); + } + else if ( tryLowerCase ) { + // try again, but lowercase the key + results = extractParameter( key.toLowerCase(), options, false ); + } + return results; + } + @Command(identifier = "prison findCmd", description = "For internal use only. Do not use. This command is used by internal code to look up " + @@ -1301,6 +1384,83 @@ public void supportSetName(CommandSender sender, + @Command(identifier = "prison support saveToFile", + description = "This sets the target of the support data to a local file.", + onlyPlayers = false, permissions = "prison.debug" ) + public void supportSaveToFile(CommandSender sender, + @Wildcard(join=true) + @Arg(name = "options", + description = "Enables, or disables the support file. 'basic' will enable the support file " + + "and add 'version', 'ranks', 'mines, and 'configs to the file automatically. " + + "Defaults to 'enable'. [enable, basic, disable]" ) + String options + ) { + + + if ( getSupportName() == null || getSupportName().trim().isEmpty() ) { + sender.sendMessage( "The support name needs to be set prior to using this command." ); + sender.sendMessage( "Use &7/prison support setSupportName help" ); + + return; + } + + + if ( options != null && options.toLowerCase().startsWith( "disable" ) ) { + + setSupportFile( null ); + } + else { + + setSupportFile( new PrisonSupportFiles() ); + getSupportFile().setupSupportFile( getSupportName() ); + } + + + + sender.sendMessage( String.format( "Save the support data to file: %b", + getSupportFile() != null ) ); + + if ( getSupportFile() != null ) { + sender.sendMessage( "You can now use the support submit options and they will be save to files." ); + + sender.sendMessage( " Your support save file location: " + + getSupportFile().getSupportFile().getAbsolutePath() ); + + if ( options.toLowerCase().equals( "basic" ) ) { + + StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitBasic(); + + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'basic' data was just added to the support output file." ); + sender.sendMessage(" - Includes: version, listeners, command stats, ladders, Ranks, Mines, and all Config files." ); + sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); + +// supportSubmitVersion(sender); +// supportSubmitRanks(sender); +// supportSubmitMines(sender); +// supportSubmitConfigs(sender); + } + } + else { + sender.sendMessage( "Support save file has been disabled. Support files have not been removed." ); + } + } + + + @Command(identifier = "prison support colorTest", + description = "Displays a test swatch of minecraft colors .", + onlyPlayers = false, permissions = "prison.debug" ) + public void supportColorTest(CommandSender sender + ) { + + StringBuilder sb = Prison.get().getPrisonStatsUtil().getColorTest(); + + for (String line : sb.toString().split("\n")) { + Output.get().logInfo(line); + } + } + @Command(identifier = "prison support submit version", description = "For Prison support: This will copy the contents of '/prison version all' " + "to paste.helpch.at so it can be easily shared with Prison's support staff .", @@ -1317,7 +1477,11 @@ public void supportSubmitVersion(CommandSender sender } - StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitVersionData(); + StringBuilder text = new StringBuilder(); + + text.append( "NOTE: Listeners and Configs information is provided below.\n\n" ); + + text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitVersionData() ); int idx = text.indexOf("{br}"); while ( idx != -1 ) { @@ -1335,86 +1499,114 @@ public void supportSubmitVersion(CommandSender sender ); // Include the command stats: - text.append( "\n\n" ); - List cmdStats = getCommandStats(); - for (String cmd : cmdStats) { - text.append( cmd ).append( "\n" ); - } + text.append( Prison.get().getPrisonStatsUtil().getCommandStatsDetailData() ); +// text.append( "\n\n" ); +// List cmdStats = getCommandStats(); +// for (String cmd : cmdStats) { +// text.append( cmd ).append( "\n" ); +// } // Include Prison backup logs: - text.append( "\n\n" ); - text.append( "Prison Backup Logs:" ).append( "\n" ); - List backupLogs = getPrisonBackupLogs(); - - for (String log : backupLogs) { - text.append( Output.decodePercentEncoding(log) ).append( "\n" ); - } - - - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = pasteChat.post( text.toString() ); - - getSupportURLs().put( "Submit version:", helpURL ); - - if ( helpURL != null ) { - - sender.sendMessage( "Prison's support information has been pasted. Copy and " + - "paste this URL in to Prison's Discord server." ); - sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); - } - else { - sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); - } - - - } - + text.append( Prison.get().getPrisonStatsUtil().getPrisonBackupLogsData() ); +// text.append( "\n\n" ); +// text.append( "Prison Backup Logs:" ).append( "\n" ); +// List backupLogs = getPrisonBackupLogs(); +// +// for (String log : backupLogs) { +// text.append( Output.decodePercentEncoding(log) ).append( "\n" ); +// } - - @Command(identifier = "prison support submit configs", - description = "For Prison support: This will copy the contents of Prison's config " + - "file to paste.helpch.at so it can be easily shared with Prison's " + - "support staff. This will include the following: config.yml plugin.yml " + - "autoFeaturesConfig.yml modules.yml module_conf/mines/config.json " + - "SellAllConfig.yml GuiConfig.yml backpacks/backpacksconfig.yml", - onlyPlayers = false, permissions = "prison.debug" ) - public void supportSubmitConfigs(CommandSender sender - ) { - - - if ( getSupportName() == null || getSupportName().trim().isEmpty() ) { - sender.sendMessage( "The support name needs to be set prior to using this command." ); - sender.sendMessage( "Use &7/prison support setSupportName help" ); - - return; - } - - StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitConfigsData(); - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitConfigsData() ); - String helpURL = pasteChat.postKeepColorCodes( text.toString() ); - getSupportURLs().put( "Submit configs:", helpURL ); - if ( helpURL != null ) { + if ( getSupportFile() != null ) { - sender.sendMessage( "Prison's support information has been pasted. Copy and " + - "paste this URL in to Prison's Discord server." ); - sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'version' data was just added to the support output file." ); + sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); } else { - sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + + PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + + String helpURL = pasteChat.post( text.toString() ); + + getSupportURLs().put( "Submit version:", helpURL ); + + if ( helpURL != null ) { + + sender.sendMessage( "Prison's support information has been pasted. Copy and " + + "paste this URL in to Prison's Discord server." ); + sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + } + else { + sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + } + } } + +// @Command(identifier = "prison support submit configs", +// description = "For Prison support: This will copy the contents of Prison's config " + +// "file to paste.helpch.at so it can be easily shared with Prison's " + +// "support staff. This will include the following: config.yml plugin.yml " + +// "autoFeaturesConfig.yml modules.yml module_conf/mines/config.json " + +// "SellAllConfig.yml GuiConfig.yml backpacks/backpacksconfig.yml", +// onlyPlayers = false, permissions = "prison.debug" ) +// public void supportSubmitConfigs(CommandSender sender +// ) { +// +// +// if ( getSupportName() == null || getSupportName().trim().isEmpty() ) { +// sender.sendMessage( "The support name needs to be set prior to using this command." ); +// sender.sendMessage( "Use &7/prison support setSupportName help" ); +// +// return; +// } +// +// StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitConfigsData(); +// +// +// +// if ( getSupportFile() != null ) { +// +// getSupportFile().saveToSupportFile( text, getSupportName() ); +// +// sender.sendMessage(" - Support 'configs' data was just added to the support output file." ); +// sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); +// } +// else { +// +// PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); +// +// String helpURL = pasteChat.postKeepColorCodes( text.toString() ); +// +// getSupportURLs().put( "Submit configs:", helpURL ); +// +// if ( helpURL != null ) { +// +// sender.sendMessage( "Prison's support information has been pasted. Copy and " + +// "paste this URL in to Prison's Discord server." ); +// sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); +// } +// else { +// sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); +// } +// +// } +// } + + @Command(identifier = "prison support submit ranks", description = "For Prison support: This will copy the contents of Prison's " + "ladders and ranks configs to paste.helpch.at so it can be " + @@ -1432,26 +1624,39 @@ public void supportSubmitRanks(CommandSender sender } + // List Ladder and rank lists: StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitRanksData(); + // List rank files: + text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitRanksFileData() ); - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = pasteChat.post( text.toString() ); - getSupportURLs().put( "Submit ranks:", helpURL ); - - if ( helpURL != null ) { + if ( getSupportFile() != null ) { - sender.sendMessage( "Prison's support information has been pasted. Copy and " + - "paste this URL in to Prison's Discord server." ); - sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'ranks' data was just added to the support output file." ); + sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); } else { - sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + + PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + + String helpURL = pasteChat.post( text.toString() ); + + getSupportURLs().put( "Submit ranks:", helpURL ); + + if ( helpURL != null ) { + + sender.sendMessage( "Prison's support information has been pasted. Copy and " + + "paste this URL in to Prison's Discord server." ); + sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + } + else { + sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + } } - } @@ -1476,23 +1681,32 @@ public void supportSubmitMines(CommandSender sender StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitMinesData(); - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = pasteChat.post( text.toString() ); - - getSupportURLs().put( "Submit mines:", helpURL ); - - if ( helpURL != null ) { + if ( getSupportFile() != null ) { - sender.sendMessage( "Prison's support information has been pasted. Copy and " + - "paste this URL in to Prison's Discord server." ); - sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'mines' data was just added to the support output file." ); + sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); } else { - sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + + PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + + String helpURL = pasteChat.post( text.toString() ); + + getSupportURLs().put( "Submit mines:", helpURL ); + + if ( helpURL != null ) { + + sender.sendMessage( "Prison's support information has been pasted. Copy and " + + "paste this URL in to Prison's Discord server." ); + sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); + } + else { + sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); + } } - } @@ -1756,43 +1970,43 @@ private void readFileToStringBulider( File textFile, StringBuilder text ) } - @Command(identifier = "prison support submit listeners", - description = "For Prison support: This will copy the server's active listeners " + - "for blockBreak, chat, and playerInteracts to paste.helpch.at so it can be " + - "easily shared with Prison's support staff.", - onlyPlayers = false, permissions = "prison.debug" ) - public void supportSubmitListeners(CommandSender sender - ) { - - - if ( getSupportName() == null || getSupportName().trim().isEmpty() ) { - sender.sendMessage( "The support name needs to be set prior to using this command." ); - sender.sendMessage( "Use &7/prison support setSupportName help" ); - - return; - } - - - StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitListenersData( "all" ); - - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = pasteChat.post( text.toString() ); - - getSupportURLs().put( "Submit Listeners:", helpURL ); - - if ( helpURL != null ) { - - sender.sendMessage( "Prison's support information has been pasted. Copy and " + - "paste this URL in to Prison's Discord server." ); - sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); - } - else { - sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); - } - - - } +// @Command(identifier = "prison support submit listeners", +// description = "For Prison support: This will copy the server's active listeners " + +// "for blockBreak, chat, and playerInteracts to paste.helpch.at so it can be " + +// "easily shared with Prison's support staff.", +// onlyPlayers = false, permissions = "prison.debug" ) +// public void supportSubmitListeners(CommandSender sender +// ) { +// +// +// if ( getSupportName() == null || getSupportName().trim().isEmpty() ) { +// sender.sendMessage( "The support name needs to be set prior to using this command." ); +// sender.sendMessage( "Use &7/prison support setSupportName help" ); +// +// return; +// } +// +// +// StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitListenersData( "all" ); +// +// PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); +// +// String helpURL = pasteChat.post( text.toString() ); +// +// getSupportURLs().put( "Submit Listeners:", helpURL ); +// +// if ( helpURL != null ) { +// +// sender.sendMessage( "Prison's support information has been pasted. Copy and " + +// "paste this URL in to Prison's Discord server." ); +// sender.sendMessage( String.format( "Paste this URL: %s", helpURL )); +// } +// else { +// sender.sendMessage( "There was an error trying to generate the paste.helpch.at URL." ); +// } +// +// +// } @@ -1882,7 +2096,8 @@ public void supportBackupList( CommandSender sender ) { ChatDisplay display = new ChatDisplay("Prison Backup Logs:"); - List backupLogs = getPrisonBackupLogs(); + List backupLogs = Prison.get().getPrisonStatsUtil().getPrisonBackupLogs(); +// List backupLogs = getPrisonBackupLogs(); for (String log : backupLogs) { display.addText(log); @@ -1892,11 +2107,11 @@ public void supportBackupList( CommandSender sender ) { } - private List getPrisonBackupLogs() { - PrisonBackups prisonBackup = new PrisonBackups(); - List backupLogs = prisonBackup.backupReport02BackupLog(); - return backupLogs; - } +// private List getPrisonBackupLogs() { +// PrisonBackups prisonBackup = new PrisonBackups(); +// List backupLogs = prisonBackup.backupReport02BackupLog(); +// return backupLogs; +// } @Command(identifier = "prison tokens balance", @@ -2010,6 +2225,18 @@ public void tokensAdd( CommandSender sender, } Player player = getPlayer( playerName ); + + if ( player == null ) { + if ( !silent ) { + sender.sendMessage( + String.format( + "Prison Tokens add: Player name not found. [%s] (hardCodedMessag)", + playerName )); + } + return; + } + + PlayerCachePlayerData pCache = player.getPlayerCachePlayerData(); long tokenBal = pCache.getTokens(); @@ -2109,6 +2336,18 @@ public void tokensRemove( CommandSender sender, Player player = getPlayer( playerName ); + + if ( player == null ) { + if ( !silent ) { + sender.sendMessage( + String.format( + "Prison Tokens remove: Player name not found. [%s] (hardCodedMessag)", + playerName )); + } + return; + } + + if ( forcePlayer ) { player.getPlayerCachePlayerData().removeTokens( amount ); @@ -2182,6 +2421,17 @@ public void tokensSet( CommandSender sender, // DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); Player player = getPlayer( playerName ); + + + if ( player == null ) { + if ( !silent ) { + sender.sendMessage( + String.format( + "Prison Tokens set: Player name not found. [%s] (hardCodedMessag)", + playerName )); + } + return; + } // // Set to zero: // long totalTokens = player.getPlayerCachePlayerData().getTokens(); @@ -2298,6 +2548,13 @@ public void setSupportName( String supportName ) { this.supportName = supportName; } + public PrisonSupportFiles getSupportFile() { + return supportFile; + } + public void setSupportFile(PrisonSupportFiles supportFile) { + this.supportFile = supportFile; + } + public TreeMap getSupportURLs() { return supportURLs; } 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 b2498aff3..b093c7a5a 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 @@ -127,6 +127,10 @@ public enum AutoFeatures { PrisonEnchantsExplosiveEventPriority(blockBreakEvents, "DISABLED"), + XPrisonExplosionTriggerEventPriority(blockBreakEvents, "DISABLED"), + XPrisonLayerTriggerEventPriority(blockBreakEvents, "DISABLED"), + XPrisonNukeTriggerEventPriority(blockBreakEvents, "DISABLED"), + blockBreakEvents__ReadMe(blockBreakEvents, "Use the following event priorities with the blockBreakEvents: " + @@ -180,12 +184,45 @@ public enum AutoFeatures { isAutoSellPerBlockBreakEnabled(inventory, false), + permissionAutoSellPerBlockBreakEnabled(inventory, "prison.automanager.autosell"), + permissionAutoSellPerBlockBreakEnabled__readme(inventory, + "AutoSell by permission can be disabled with the use of 'disable', " + + "or 'false', for the perm name. " + + "Players cannot use the autosell permission while OP'd."), + - permissionAutoSellPerBlockBreakEnabled__ReadMe(inventory, - "If OP then you cannot use this permission node since it would always " + - "be enabled. Using a value of 'disable' will turn it off for everyone."), + +// permissionAutoSellPerBlockBreakEnabled__ReadMe(inventory, +// "If OP then you cannot use this permission node since it would always " + +// "be enabled. Using a value of 'disable' will turn it off for everyone."), // + isAutoSellLeftoversForceDebugLogging(inventory, true), + isAutoSellLeftoversForceDebugLogging__ReadMe(inventory, + "If autosell is enabled and could not sell all blocks, then force " + + "Prison's debug logging of transaction to help identify why. This only " + + "applies if debug mode is turned off."), + + + isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires(inventory, false), + isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires__readme(inventory, + "AutoManager's autosell does not touch the player's inventory. So this feature " + + "will perform a sellall on the player's inventory at the end of handling " + + "the bukkkit's BlockBreakEvent. This will not apply to anyother event. " + + "This can be enabled without enabling the autosell."), + + + isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires(inventory, false), + isEnabledDelayedSellAllOnInventoryDelayInTicks(inventory, 2), + isEnabledDelayedSellAllOnInventoryDelayInTicks__readme(inventory, + "This option adds a delay to a sellall event. The delay can be set to " + + "a range of 0 or more ticks, with 2 ticks being the default. When a " + + "player breaks a block through the BlockBreakEvent, if this is enabled, " + + "then a task will be submitted to perform a sellall transaction for " + + "the player. Only one task per player can be submitted at a time, so " + + "if the player is agressivly mining, they cannot queue up many sellalls."), + + // isAutoSellPerBlockBreakInlinedEnabled(general, false), isAutoSellIfInventoryIsFull(inventory, true), @@ -273,6 +310,8 @@ public enum AutoFeatures { isCalculateFortuneEnabled(fortuneFeature, true), + isUseTokenEnchantsFortuneLevel(fortuneFeature, false ), + fortuneMultiplierGlobal(fortuneFeature, 1.0 ), fortuneMultiplierMax(fortuneFeature, 0 ), @@ -293,7 +332,40 @@ public enum AutoFeatures { isCalculateAltFortuneOnAllBlocksEnabled(fortuneFeature, false), + percentGradientFortune(fortuneFeature), + isPercentGradientFortuneEnabled(percentGradientFortune, false), + isPercentGradientFortuneEnabled__readme(percentGradientFortune, + "Percent Gradient Fortune is an alternative fortune calculation that " + + "will only be enabled if extendedBukkitFortune and altFortune is " + + "turned off. Percent Gradient Fortune will always drop a minimum of " + + "1 block with fortune 0 and higher. The max it will ever drop, will " + + "be 1 + MaxBonusBlocks amount. The calculation of the MaxBonusBlocks " + + "will be a random roll resulting in 0 bonus blocks, to the MaxBonusBlocks " + + "amount IF the player has the max fortune on their tool. For fortune " + + "ammounts less than the maxFortuneLevel, it will be treated as a " + + "linear percentage gradient of the max amount. " + + "For example, MaxFortuneLevel= 1000, and MaxBonusBlocks= 200. " + + "Therefore if the player has a fortune 500, the max bonus they could get would " + + "be only 100 blocks, but could be as low as zero bonus blocks since it's a random " + + "roll on each calculation. If they have a fort 250, then it will be 25% of 200, or 50 " + + "blocks as a max bonus. " + + "For better control of the randomness applied to the bonus block calculations, " + + "the MinPercentRandomness sets the lowest range for the randomness. What this means, " + + "is for a maxFortuneLevel= 1000 and a maxBonusBlocks of= 200, and a tool with " + + "fort 500, the calcs would be for a bonus between '0' and (500 / 1000 * 200 =) 100 " + + "bonus blocks. But with the minPercentRandomness= 25, then the range would be " + + "'25%' to 100% of the 100 bonus blocks. The minePercentRandomness would ensure a " + + "higher payout of bonus blocks, without effecting the max payout. " + + "minPercentRandomness has a valid range of 0.0 (off) to 99.0 percent. " + + "No other fortune multipliers will apply to these calculations. The percentage " + + "gradient is a very controlled way of paying out fortune bonuses."), + + percentGradientFortuneMaxFortuneLevel(percentGradientFortune, 1000 ), + percentGradientFortuneMaxBonusBlocks(percentGradientFortune, 200 ), + + percentGradientFortuneMinPercentRandomness(percentGradientFortune, 25.0 ), + pickupFeature(options), @@ -360,6 +432,21 @@ public enum AutoFeatures { blockCopperBlock(blockFeature, true), + + blockConverters(options), + isEnabledBlockConverters(blockConverters, false ), + + blockConverters_readme(blockConverters, + "Block converters are a new experimental component to prison that will " + + "provide much more control over all things related to blocks, including " + + "access through perms, ranks, or special functional behaviors. Eventually " + + "this will replace the list of hard coded blocks listed above for " + + "blocking and smelting."), + + isEnabledBlockConvertersEventTriggers(blockConverters, false ) + + + // examplesOnlyNotUsed, // exampleOfBlockConversions(examplesOnlyNotUsed), // @@ -1034,6 +1121,7 @@ public TreeMap getBstatsDetails() { bStatsDetailPriority( AutoFeatures.blockBreakEventPriority, tm ); bStatsDetailPriority( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority, tm ); + bStatsDetailPriority( AutoFeatures.TokenEnchantBlockExplodeEventPriority, tm ); bStatsDetailPriority( AutoFeatures.CrazyEnchantsBlastUseEventPriority, tm ); bStatsDetailPriority( AutoFeatures.RevEnchantsExplosiveEventPriority, tm ); @@ -1042,15 +1130,44 @@ public TreeMap getBstatsDetails() { bStatsDetailPriority( AutoFeatures.ZenchantmentsBlockShredEventPriority, tm ); bStatsDetailPriority( AutoFeatures.PrisonEnchantsExplosiveEventPriority, tm ); + bStatsDetailPriority( AutoFeatures.XPrisonExplosionTriggerEventPriority, tm ); + bStatsDetailPriority( AutoFeatures.XPrisonLayerTriggerEventPriority, tm ); + bStatsDetailPriority( AutoFeatures.XPrisonNukeTriggerEventPriority, tm ); + + bStatsDetailBoolean( AutoFeatures.isCalculateFoodExhustion, tm ); + bStatsDetailBoolean( AutoFeatures.isCalculateSilkEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.isCalculateDropAdditionsEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.isCalculateXPEnabled, tm ); bStatsDetailBoolean( AutoFeatures.givePlayerXPAsOrbDrops, tm ); + bStatsDetailBoolean( AutoFeatures.ifBlockIsAlreadyCountedThenCancelEvent, tm ); + bStatsDetailBoolean( AutoFeatures.processMonitorEventsOnlyIfPrimaryBlockIsAIR, tm ); + bStatsDetailBoolean( AutoFeatures.isMinecraftStatsReportingEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine, tm ); + + + + bStatsDetailBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.permissionAutoSellPerBlockBreakEnabled, tm ); + + bStatsDetailPriority( AutoFeatures.isAutoSellLeftoversForceDebugLogging, tm ); + bStatsDetailPriority( AutoFeatures.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires, tm ); + + bStatsDetailPriority( AutoFeatures.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires, tm ); + bStatsDetailPriority( AutoFeatures.isEnabledDelayedSellAllOnInventoryDelayInTicks, tm ); + bStatsDetailBoolean( AutoFeatures.isAutoSellIfInventoryIsFull, tm ); + bStatsDetailBoolean( AutoFeatures.isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority, tm ); bStatsDetailBoolean( AutoFeatures.dropItemsIfInventoryIsFull, tm ); + bStatsDetailBoolean( AutoFeatures.actionBarMessageIfInventoryIsFull, tm ); + + + bStatsDetailBoolean( AutoFeatures.isAutoFeaturesEnabled, tm ); if ( isFeatureBoolean( AutoFeatures.isAutoFeaturesEnabled ) ) { @@ -1070,11 +1187,32 @@ public TreeMap getBstatsDetails() { bStatsDetailBoolean( AutoFeatures.tokensEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.tokensBlocksPerToken, tm ); + + + bStatsDetailBoolean( AutoFeatures.isLoreEnabled, tm ); + if ( isFeatureBoolean( AutoFeatures.isLoreEnabled )) { + + bStatsDetailBoolean( AutoFeatures.loreTrackBlockBreakCount, tm ); + bStatsDetailBoolean( AutoFeatures.loreDurabiltyResistance, tm ); + } + + + bStatsDetailBoolean( AutoFeatures.isCalculateDurabilityEnabled, tm ); bStatsDetailBoolean( AutoFeatures.isPreventToolBreakage, tm ); + bStatsDetailBoolean( AutoFeatures.preventToolBreakageThreshold, tm ); + + + bStatsDetailBoolean( AutoFeatures.isCalculateFortuneEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.fortuneMultiplierGlobal, tm ); + bStatsDetailBoolean( AutoFeatures.fortuneMultiplierMax, tm ); + bStatsDetailBoolean( AutoFeatures.fortuneBukkitDropsMultiplier, tm ); + bStatsDetailBoolean( AutoFeatures.isExtendBukkitFortuneCalculationsEnabled, tm ); + bStatsDetailBoolean( AutoFeatures.isCalculateAltFortuneEnabled, tm ); bStatsDetailBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled, tm ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesWrapper.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesWrapper.java index 4131b2abf..1439c45dd 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesWrapper.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesWrapper.java @@ -13,17 +13,17 @@ public class AutoFeaturesWrapper private AutoFeaturesFileConfig autoFeaturesConfig = null; - private BlockConvertersFileConfig blockConvertersConfig = null; + private static BlockConvertersFileConfig blockConvertersConfig = null; private AutoFeaturesWrapper() { super(); this.autoFeaturesConfig = new AutoFeaturesFileConfig(); - if ( Output.get().isDebug() ) { +// if ( Output.get().isDebug() ) { - this.blockConvertersConfig = new BlockConvertersFileConfig(); - } +// this.blockConvertersConfig = new BlockConvertersFileConfig(); +// } } public static AutoFeaturesWrapper getInstance() { @@ -40,26 +40,42 @@ public static AutoFeaturesWrapper getInstance() { } + public static BlockConvertersFileConfig getBlockConvertersInstance() { + if ( blockConvertersConfig == null ) { + + synchronized ( BlockConvertersFileConfig.class ) { + if ( blockConvertersConfig == null ) { + + blockConvertersConfig = new BlockConvertersFileConfig(); + +// blockConvertersConfig.reloadConfig(); + } + } + } + return blockConvertersConfig; + } + + public void reloadConfigs() { getAutoFeaturesConfig().reloadConfig(); - if ( Output.get().isDebug() && getBlockConvertersConfig() != null ) { - - getBlockConvertersConfig().reloadConfig(); - } +// if ( Output.get().isDebug() && getBlockConvertersConfig() != null ) { +// +// getBlockConvertersConfig().reloadConfig(); +// } } public AutoFeaturesFileConfig getAutoFeaturesConfig() { return autoFeaturesConfig; } - public BlockConvertersFileConfig getBlockConvertersConfig() { - return blockConvertersConfig; - } - - public void setBlockConvertersConfig(BlockConvertersFileConfig blockConvertersConfig) { - this.blockConvertersConfig = blockConvertersConfig; - } +// public BlockConvertersFileConfig getBlockConvertersConfig() { +// return blockConvertersConfig; +// } +// +// public void setBlockConvertersConfig(BlockConvertersFileConfig blockConvertersConfig) { +// this.blockConvertersConfig = blockConvertersConfig; +// } public boolean isBoolean( AutoFeatures feature ) { return autoFeaturesConfig.isFeatureBoolean( feature ); @@ -88,4 +104,5 @@ public List getListString( AutoFeatures feature ) { return results; } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverter.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverter.java index 34b4678d7..7575a7225 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverter.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverter.java @@ -19,6 +19,8 @@ public class BlockConverter { private ArrayList permissions; private ArrayList outputs; + +// private ArrayList options; public BlockConverter( String blockName, int keyQuantity ) { super(); @@ -32,6 +34,8 @@ public BlockConverter( String blockName, int keyQuantity ) { this.permissions = new ArrayList<>(); this.outputs = new ArrayList<>(); + +// this.options = new ArrayList<>(); } public BlockConverter( String blockName, int keyQuantity, String mininumSpigotSemanticVersion ) { @@ -236,4 +240,11 @@ public void setOutputs(ArrayList outputs) { this.outputs = outputs; } +// public ArrayList getOptions() { +// return options; +// } +// public void setOptions(ArrayList options) { +// this.options = options; +// } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterEventTrigger.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterEventTrigger.java new file mode 100644 index 000000000..0392d5cfc --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterEventTrigger.java @@ -0,0 +1,32 @@ +package tech.mcprison.prison.autofeatures; + +import java.util.ArrayList; + +public class BlockConverterEventTrigger + extends BlockConverter { + + private ArrayList options; + + public BlockConverterEventTrigger( String blockName, int keyQuantity ) { + super( blockName, keyQuantity ); + + this.options = new ArrayList<>(); + } + + public BlockConverterEventTrigger( String blockName, int keyQuantity, String mininumSpigotSemanticVersion ) { + super( blockName, keyQuantity, mininumSpigotSemanticVersion ); + + this.options = new ArrayList<>(); + } + + public BlockConverterEventTrigger( String blockName ) { + this( blockName, 1 ); + } + + public ArrayList getOptions() { + return options; + } + public void setOptions(ArrayList options) { + this.options = options; + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptionEventTrigger.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptionEventTrigger.java new file mode 100644 index 000000000..bf20a5ad8 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptionEventTrigger.java @@ -0,0 +1,96 @@ +package tech.mcprison.prison.autofeatures; + +/** + *

The event trigger uses the block type that this is associated with to + * identify when it should apply. + *

+ * + */ +public class BlockConverterOptionEventTrigger +// extends BlockConverterOptions + { + +// private String blockTriggerName; + + private String eventPluginName; + + private String description; + + private String eventPluginPriority; + + private String eventPluginClassName; + + private boolean allowPrisonToProccessDrops; + + private boolean removeBlockWithoutDrops; + + private boolean ignoreBlockInExplosionEvents; + + /** + * This is to be used as a transient cache of working with + * the external event. + */ + private transient Object externalResource; + + public BlockConverterOptionEventTrigger() { + super(); +// super( BlockConverterOptionType.event_trigger ); + } + + public String getEventPluginName() { + return eventPluginName; + } + public void setEventPluginName(String eventPluginName) { + this.eventPluginName = eventPluginName; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getEventPluginPriority() { + return eventPluginPriority; + } + public void setEventPluginPriority(String eventPluginPriority) { + this.eventPluginPriority = eventPluginPriority; + } + + public String getEventPluginClassName() { + return eventPluginClassName; + } + public void setEventPluginClassName(String eventPluginClassName) { + this.eventPluginClassName = eventPluginClassName; + } + + public boolean isAllowPrisonToProccessDrops() { + return allowPrisonToProccessDrops; + } + public void setAllowPrisonToProccessDrops(boolean allowPrisonToProccessDrops) { + this.allowPrisonToProccessDrops = allowPrisonToProccessDrops; + } + + public boolean isRemoveBlockWithoutDrops() { + return removeBlockWithoutDrops; + } + public void setRemoveBlockWithoutDrops(boolean removeBlockWithoutDrops) { + this.removeBlockWithoutDrops = removeBlockWithoutDrops; + } + + public boolean isIgnoreBlockInExplosionEvents() { + return ignoreBlockInExplosionEvents; + } + public void setIgnoreBlockInExplosionEvents(boolean ignoreBlockInExplosionEvents) { + this.ignoreBlockInExplosionEvents = ignoreBlockInExplosionEvents; + } + + public Object getExternalResource() { + return externalResource; + } + public void setExternalResource(Object externalResource) { + this.externalResource = externalResource; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptions.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptions.java new file mode 100644 index 000000000..ad17544ce --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConverterOptions.java @@ -0,0 +1,27 @@ +package tech.mcprison.prison.autofeatures; + +public abstract class BlockConverterOptions { + + private final BlockConverterOptionType blockConverterOptionType; + + public BlockConverterOptions() { + super(); + + this.blockConverterOptionType = BlockConverterOptionType.no_options_set; + } + public BlockConverterOptions( BlockConverterOptionType optionType ) { + super(); + + this.blockConverterOptionType = optionType; + } + + public enum BlockConverterOptionType { + no_options_set, + event_trigger; + } + + public BlockConverterOptionType getBlockConverterOptionType() { + return blockConverterOptionType; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersData.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersData.java new file mode 100644 index 000000000..32939ac97 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersData.java @@ -0,0 +1,73 @@ +package tech.mcprison.prison.autofeatures; + +import java.util.TreeMap; + +import tech.mcprison.prison.autofeatures.BlockConvertersFileConfig.BlockConverterTypes; +import tech.mcprison.prison.file.FileIOData; + +public class BlockConvertersData + implements FileIOData +{ + + private TreeMap> blockConverters; + private TreeMap blockConvertersEventTiggers; + + private TreeMap processAutoFeaturesAllBlocks = null; + + public BlockConvertersData() { + super(); + + this.blockConverters = new TreeMap<>(); + this.blockConvertersEventTiggers = new TreeMap<>(); + + this.processAutoFeaturesAllBlocks = new TreeMap<>(); + } + + + + /** + *

Force the BlockConverterEventTriggers to BlockConverter so it can be + * processed by the core selectors that deal with BlockConverter objects + * and the player's. + *

+ * + * @param blockName + * @return + */ + public TreeMap getBlockConvertersEventTiggers(String blockName) { + TreeMap results = new TreeMap<>(); + + String key = blockName.toLowerCase(); + + if ( getBlockConvertersEventTiggers().containsKey( key ) ) { + results.put( key, + (BlockConverter) getBlockConvertersEventTiggers().get( key ) + ); + } + + return results; + } + + + public TreeMap> getBlockConverters() { + return blockConverters; + } + public void setBlockConverters(TreeMap> blockConverters) { + this.blockConverters = blockConverters; + } + + public TreeMap getBlockConvertersEventTiggers() { + return blockConvertersEventTiggers; + } + public void setBlockConvertersEventTiggers(TreeMap blockConvertersEventTiggers) { + this.blockConvertersEventTiggers = blockConvertersEventTiggers; + } + + public TreeMap getProcessAutoFeaturesAllBlocks() { + return processAutoFeaturesAllBlocks; + } + public void setProcessAutoFeaturesAllBlocks(TreeMap processAutoFeaturesAllBlocks) { + this.processAutoFeaturesAllBlocks = processAutoFeaturesAllBlocks; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersFileConfig.java index 5bd4210a0..14c28cb42 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersFileConfig.java @@ -3,45 +3,59 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.TreeMap; import tech.mcprison.prison.Prison; -import tech.mcprison.prison.file.FileIOData; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; -import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.output.Output; -public class BlockConvertersFileConfig - implements FileIOData { +public class BlockConvertersFileConfig { public static final String FILE_NAME__BLOCK_CONVERTS_CONFIG_JSON = "/blockConvertersConfig.json"; private transient File configFile; - private TreeMap> blockConverters; + private transient BlockConvertersData bcData; - private TreeMap processAutoFeaturesAllBlocks = null; + private transient List eventTriggerBlockNames; +// private TreeMap> blockConverters; +// private TreeMap blockConvertersEventTiggers; + + +// private TreeMap processAutoFeaturesAllBlocks = null; public enum BlockConverterTypes { aSample01, autoPickupFeatures, blockFeatures, - smeltFeatures + smeltFeatures, + eventTriggers ; } public BlockConvertersFileConfig() { super(); - this.blockConverters = new TreeMap<>(); + this.bcData = new BlockConvertersData(); + + this.eventTriggerBlockNames = null; + +// this.blockConverters = new TreeMap<>(); +// this.blockConvertersEventTiggers = new TreeMap<>(); +// +// this.processAutoFeaturesAllBlocks = new TreeMap<>(); - this.processAutoFeaturesAllBlocks = new TreeMap<>(); + reloadConfig(); } - public boolean processAutoFeaturesForBlock( RankPlayer player, String blockName ) { + public boolean processAutoFeaturesForBlock( Player player, String blockName ) { boolean results = isProcessAutoFeaturesAllBlocks( player ); if ( !results ) { @@ -51,7 +65,7 @@ public boolean processAutoFeaturesForBlock( RankPlayer player, String blockName return results; } - public BlockConverterResults getBlockConverterItemStacks( RankPlayer player, + public BlockConverterResults getBlockConverterItemStacks( Player player, String blockName, int blockQuantity, BlockConverterTypes bcType ) { @@ -112,13 +126,14 @@ public BlockConverterResults getBlockConverterItemStacks( RankPlayer player, * @param blockName * @return */ - public BlockConverter getBlockConverter( RankPlayer player, String blockName, + public BlockConverter getBlockConverter( Player player, String blockName, BlockConverterTypes bcType ) { BlockConverter results = null; if ( player != null && blockName != null && bcType != null ) { BlockConverter temp = getBlockConverter( blockName, bcType ); + if ( temp != null && temp.getPermissions().size() == 0 ) { results = temp; } @@ -150,10 +165,20 @@ public BlockConverter getBlockConverter( String blockName, BlockConverterTypes b if ( blockName != null && bcType != null ) { - TreeMap bConverters = getBlockConverters().get(bcType); + TreeMap bConverters = null; + + String key = blockName.toLowerCase(); + + if ( bcType == BlockConverterTypes.eventTriggers ) { + bConverters = getBcData().getBlockConvertersEventTiggers( key ); + } + else { + + bConverters = getBcData().getBlockConverters().get(bcType); + } - if ( bConverters.containsKey( blockName.toLowerCase() ) ) { - results = bConverters.get( blockName.toLowerCase() ); + if ( bConverters.containsKey( key ) ) { + results = bConverters.get( key ); } } @@ -169,7 +194,7 @@ public BlockConverter getBlockConverter( String blockName, BlockConverterTypes b * @param bc * @return */ - private List getBlockConverterOutputs(RankPlayer player, BlockConverter bc) { + private List getBlockConverterOutputs(Player player, BlockConverter bc) { List outputs = new ArrayList<>(); @@ -177,7 +202,7 @@ private List getBlockConverterOutputs(RankPlayer player, B for ( BlockConverterOutput bcOutput : bc.getOutputs() ) { - if ( bcOutput.isEnabled() ) { + if ( bcOutput.isEnabled() ) { // If chance, and the random number is greater than the chance, then skip this output: if ( bcOutput.getChance() != null && @@ -214,17 +239,60 @@ private List getBlockConverterOutputs(RankPlayer player, B return outputs; } + /** + *

This function will take a player, and check if that player should have the ability to process all + * blocks under auto features. This is the "global" setting that bypasses checking individual block types. + *

+ * + *

If the auto features settings `options.autoFeatures.isAutoFeaturesEnabled: false` is + * disabled (set to false), then this will apply to the normal drops if + * `options.normalDrop.handleNormalDropsEvents: true' is enabled (set to true). + * If both of those are set to disabled, then no blocks will be processed. + *

+ * + * @param player + * @return + */ + public Boolean isProcessAutoFeaturesAllBlocks( Player player ) { + + if ( !getBcData().getProcessAutoFeaturesAllBlocks().containsKey( player.getName() ) ) { + BlockConverterResults allBlocksBCR = getBlockConverterItemStacks( player, "*all*", 1, BlockConverterTypes.autoPickupFeatures ); + + BlockConverter allBlocks = allBlocksBCR.getBlockConverter(); + + boolean playerAllBlocks = ( allBlocks != null && allBlocks.isEnabled() ); + + getBcData().getProcessAutoFeaturesAllBlocks().put( player.getName(), playerAllBlocks ); + } + + return getBcData().getProcessAutoFeaturesAllBlocks().get( player.getName() ); + } - + /** + *

This loads the sample block converters. If a new section is added, it will + * add the new section, along with the examples, to the existing block + * converters and then save everything. + *

+ * + *

This should only be called from the reloadConfig() function. + *

+ * + * @return + */ private boolean initialConfig() { boolean dirty = false; + // Set to null so it will auto reload on next access: + setEventTriggerBlockNames( null ); + BlockConvertersInitializer initializer = new BlockConvertersInitializer(); - dirty = initializer.checkConfigs( getBlockConverters() ); + boolean d1 = initializer.checkConfigs( getBcData().getBlockConverters() ); + boolean d2 = initializer.checkConfigsEventTrigger( getBcData().getBlockConvertersEventTiggers() ); + dirty = d1 || d2; - if ( initializer.validateBlockConverters( getBlockConverters() ) ) { + if ( initializer.validateBlockConverters( getBcData().getBlockConverters() ) ) { dirty = true; } @@ -241,63 +309,149 @@ public File getConfigFile() { return configFile; } + /** + *

This actually is how the BlockConverters are loaded and created. + * There should be no other way to load the configs. + * + * This class can be instantiated, but only if block converters are + * enabled within the AutoFeatures config file will they be loaded. + *

+ * + */ public void reloadConfig() { - JsonFileIO jfio = new JsonFileIO(); - BlockConvertersFileConfig temp = (BlockConvertersFileConfig) jfio.readJsonFile( getConfigFile(), this ); - - if ( temp != null ) { - setBlockConverters( temp.getBlockConverters() ); - } - - boolean dirty = initialConfig(); - - if ( dirty ) { - saveToJson(); + if ( AutoFeaturesWrapper.getInstance().isBoolean( AutoFeatures.isEnabledBlockConverters ) ) { + JsonFileIO jfio = new JsonFileIO(); + + BlockConvertersData temp = (BlockConvertersData) jfio.readJsonFile( getConfigFile(), getBcData() ); + + if ( temp != null ) { + setBcData( temp ); +// setBlockConverters( temp.getBlockConverters() ); + } + + boolean dirty = initialConfig(); + + if ( dirty ) { + saveToJson(); + } } + } public void saveToJson() { JsonFileIO jfio = new JsonFileIO(); - jfio.saveJsonFile(getConfigFile(), this ); + jfio.saveJsonFile(getConfigFile(), getBcData() ); + + Output.get().logDebug( + "BlockConverters: saved config file: %s", + getConfigFile().getAbsolutePath() ); } - public TreeMap> getBlockConverters() { - return blockConverters; +// public TreeMap> getBlockConverters() { +// return blockConverters; +// } +// public void setBlockConverters(TreeMap> blockConverters) { +// this.blockConverters = blockConverters; +// } +// +// public TreeMap getBlockConvertersEventTiggers() { +// return blockConvertersEventTiggers; +// } +// public void setBlockConvertersEventTiggers(TreeMap blockConvertersEventTiggers) { +// this.blockConvertersEventTiggers = blockConvertersEventTiggers; +// } + + + + public BlockConvertersData getBcData() { + return bcData; } - public void setBlockConverters(TreeMap> blockConverters) { - this.blockConverters = blockConverters; + public void setBcData(BlockConvertersData bcData) { + this.bcData = bcData; } /** - *

This function will take a player, and check if that player should have the ability to process all - * blocks under auto features. This is the "global" setting that bypasses checking individual block types. + *

This gets the BlockConverterEventTrigger for the block name provided, based upon player permissions + * if they apply. *

* - *

If the auto features settings `options.autoFeatures.isAutoFeaturesEnabled: false` is - * disabled (set to false), then this will apply to the normal drops if - * `options.normalDrop.handleNormalDropsEvents: true' is enabled (set to true). - * If both of those are set to disabled, then no blocks will be processed. - *

+ * @param rPlayer + * @param blockName + * @return + */ + public List findEventTrigger( Player rPlayer, String blockName) { + List eventTriggers = null; + + BlockConverterEventTrigger bcet = (BlockConverterEventTrigger) + getBlockConverter( rPlayer, blockName, BlockConverterTypes.eventTriggers ); + + if ( bcet != null && bcet.getOptions().size() > 0 ) { + eventTriggers = bcet.getOptions(); + } + + return eventTriggers; + } + + + + + public List getEventTriggerBlockNames() { + + if ( eventTriggerBlockNames == null ) { + eventTriggerBlockNames = findEventTriggerBlockNames(); + } + return eventTriggerBlockNames; + } + + public void setEventTriggerBlockNames(List eventTriggerBlockNames) { + this.eventTriggerBlockNames = eventTriggerBlockNames; + } + + /** + *

This function gets all of the blocks within the BlockConverterEventTriggers that should be + * ignored, and removed, from explosion events, or multi-block events. If this feature is + * enabled, then the only way to break those blocks, or to trigger those plugins that + * should handle those blocks, is by direct block breakage, and not explosion events. + *

* - * @param player + *

The list of blocks, should not be impacted by player's permissions because if they are, then + * those who do not have access to those blocks, would then be able to break those blocks, or at least + * through explosion events. + *

+ * + * @param rPlayer * @return */ - public Boolean isProcessAutoFeaturesAllBlocks( RankPlayer player ) { + private List findEventTriggerBlockNames() { + List blockNames = new ArrayList<>(); - if ( !processAutoFeaturesAllBlocks.containsKey( player.getName() ) ) { - BlockConverterResults allBlocksBCR = getBlockConverterItemStacks( player, "*all*", 1, BlockConverterTypes.autoPickupFeatures ); + TreeMap eventTriggers = getBcData().getBlockConvertersEventTiggers(); + + Set keys = eventTriggers.keySet(); + for (String key : keys) { + BlockConverterEventTrigger et = eventTriggers.get(key); - BlockConverter allBlocks = allBlocksBCR.getBlockConverter(); - - boolean playerAllBlocks = ( allBlocks != null && allBlocks.isEnabled() ); + String blockName = et.getKeyBlockName().toLowerCase(); - processAutoFeaturesAllBlocks.put( player.getName(), playerAllBlocks ); + // Confirm the BlockConverter is active: + if ( et.isEnabled() ) { + + for ( BlockConverterOptionEventTrigger eventTrigger : et.getOptions() ) { + if ( eventTrigger.isIgnoreBlockInExplosionEvents() ) { + + if ( !blockNames.contains(blockName) ) { + + blockNames.add( blockName ); + break; + } + } + } + } } - return processAutoFeaturesAllBlocks.get( player.getName() ); + return blockNames; } - - + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersInitializer.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersInitializer.java index 148aed76d..7c9cab93a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersInitializer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/BlockConvertersInitializer.java @@ -36,6 +36,20 @@ public boolean checkConfigs(TreeMap treeMap) { + boolean isDirty = false; + + if ( treeMap != null && treeMap.size() == 0 ) { + + loadDefaultBlockConvertersEventTriggers(treeMap); + + isDirty = true; + + } + + return isDirty; + } + private void loadDefaultBlockConverters( BlockConverterTypes bcType, TreeMap blockConverters ) { @@ -63,11 +77,23 @@ private void loadDefaultBlockConverters( BlockConverterTypes bcType, TreeMap blockConverters ) { + + loadDefaultEventTriggers( blockConverters ); + + } + private void loadDefaultBlockConverterSample01(TreeMap blockConverters) { @@ -92,7 +118,33 @@ private void loadDefaultBlockConverterSample01(TreeMap b blockConverters.put( bc2.getKeyBlockName(), bc2 ); } + + + private void loadDefaultEventTriggers(TreeMap blockConverters ) { + + BlockConverterEventTrigger bc1 = new BlockConverterEventTrigger( "*not_a_real_block*" ); + + bc1.getPermissions().add("prison.not.used.sample.admin"); + + BlockConverterOptionEventTrigger et1 = new BlockConverterOptionEventTrigger(); + et1.setEventPluginName( "DropEdit2" ); + et1.setDescription( "Sample of how an EventTrigger is setup. Use " + + "'/prison support listeners blockEvent' to get details."); + et1.setEventPluginPriority( "HIGHEST" ); + et1.setEventPluginClassName( "DropEdit.ListenersLegacy" ); + + et1.setAllowPrisonToProccessDrops( false ); + et1.setIgnoreBlockInExplosionEvents( true ); + et1.setRemoveBlockWithoutDrops( true ); + + bc1.getOptions().add( et1 ); + + blockConverters.put( bc1.getKeyBlockName(), bc1 ); + + } + + public void loadDefaultBlockConverterSmelters( TreeMap blockConverters ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index f7a41d20d..9f2744a9d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -179,6 +179,30 @@ public class MineBombData { private boolean autosell = false; + + private int customModelData = 0; + + + /** + *

This is a list of mine names where a mine bomb is allowed to be used. + * This setting overrides any global setting to disallow a specific mine, which + * allows a specific mine bomb to be used within a mine where all other + * mine bombs are excluded. + *

+ */ + private List allowedMines; + + /** + *

This is a list of mine names where this mine bomb cannot be used. + * This mine bomb specific list is combined with the global setting of + * excluded mines. The global settings is in `config.yml` and is named + * `prison-mines.mine-bombs.prevent-usage-in-mines`. + *

+ */ + private List preventedMines; + + + /** *

Internal just to indicated if a mine bomb is activated or not. * This has not purpose if used in a save file. @@ -201,6 +225,9 @@ public MineBombData() { this.soundEffects = new TreeSet<>( new MineBombEffectsData() ); this.visualEffects = new TreeSet<>( new MineBombEffectsData() ); + + this.allowedMines = new ArrayList<>(); + this.preventedMines = new ArrayList<>(); } @@ -244,6 +271,9 @@ public MineBombData( String name, String itemType, String explosionShape, this.glowing = false; this.gravity = true; + this.autosell = false; + this.customModelData = 0; + } @@ -281,11 +311,21 @@ public MineBombData clone() { cloned.setAutosell( isAutosell() ); cloned.setActivated( isActivated() ); + cloned.setCustomModelData( getCustomModelData() ); + for ( String l : getLore() ) { cloned.getLore().add( l ); } + for ( String mine : getAllowedMines() ) { + cloned.getAllowedMines().add( mine ); + } + + for ( String mine : getPreventedMines() ) { + cloned.getPreventedMines().add( mine ); + } + for ( MineBombEffectsData soundEffect : getSoundEffects() ) { @@ -473,6 +513,27 @@ public void setAutosell( boolean autosell ) { this.autosell = autosell; } + public int getCustomModelData() { + return customModelData; + } + public void setCustomModelData(int customModelData) { + this.customModelData = customModelData; + } + + public List getAllowedMines() { + return allowedMines; + } + public void setAllowedMines(List allowedMines) { + this.allowedMines = allowedMines; + } + + public List getPreventedMines() { + return preventedMines; + } + public void setPreventedMines(List preventedMines) { + this.preventedMines = preventedMines; + } + public boolean isActivated() { return activated; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDefaultConfigSettings.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDefaultConfigSettings.java index 89494b456..ef03e2c9b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDefaultConfigSettings.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDefaultConfigSettings.java @@ -219,6 +219,13 @@ public void setupDefaultMineBombData(MineBombs mineBombs) mbd.setToolInHandFortuneLevel( 0 ); mbd.setRemovalChance( 40.0d ); + mbd.getAllowedMines().add( "a" ); + mbd.getAllowedMines().add( "b" ); + mbd.getAllowedMines().add( "c" ); + + mbd.getPreventedMines().add( "d" ); + mbd.getPreventedMines().add( "e" ); + mbd.getSoundEffects().add( mbeSound01.clone() ); mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); mbd.getSoundEffects().add( mbeSound03.clone() ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 2f65a6392..0a1c2e592 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -5,8 +5,10 @@ import java.util.List; import java.util.Set; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; @@ -127,6 +129,9 @@ public void saveConfigJson() { File configFile = getConfigFile( fio ); + // Ensure it's set to the correct data version so it won't falsely resave on reload: + getConfigData().setDataFormatVersion( MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ); + fio.saveJsonFile( configFile, getConfigData() ); } @@ -145,9 +150,12 @@ public void loadConfigJson() { File configFile = getConfigFile( fio ); - if ( !configFile.exists() ) { + boolean configExists = configFile.exists(); + + if ( !configExists ) { MineBombDefaultConfigSettings defaultConfigs = new MineBombDefaultConfigSettings(); defaultConfigs.setupDefaultMineBombData( this ); + } else { @@ -190,8 +198,25 @@ public void loadConfigJson() { } } + } + + + StringBuilder sbMsg = new StringBuilder(); + int cnt = getConfigData().getBombs().size(); + sbMsg.append( "Prison Mine Bombs: " ) + .append( cnt ) + .append( "[" ); + + for ( String key : getConfigData().getBombs().keySet() ) { + MineBombData bomb = getConfigData().getBombs().get( key ); + sbMsg.append( " " ) + .append( bomb.getName() ); } + + sbMsg.append( " ]" ); + + Output.get().logInfo( sbMsg.toString() ); } @@ -355,6 +380,66 @@ public void validateMineBombs() isDirty = true; } + // map all names to lower case + if ( bomb.getAllowedMines().size() > 0 ) { + List mines = new ArrayList<>(); + boolean cleaned = false; + + for (String mineName : bomb.getAllowedMines() ) { + String cleanedMineName = mineName.toLowerCase(); + + if ( !cleanedMineName.equals( mineName ) ) { + cleaned = true; + } + + if ( !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { + Output.get().log( "MineBomb %s: invalid mine name for allowedMines: %s Removed.", + LogLevel.WARNING, + bomb.getName(), cleanedMineName ); + cleaned = true; + } + else { + + mines.add(cleanedMineName); + } + + } + if ( cleaned ) { + bomb.setAllowedMines(mines); + isDirty = true; + } + } + + // map all names to lower case + if ( bomb.getPreventedMines().size() > 0 ) { + List mines = new ArrayList<>(); + boolean cleaned = false; + + for (String mineName : bomb.getPreventedMines() ) { + String cleanedMineName = mineName.toLowerCase(); + + if ( !cleanedMineName.equals( mineName ) ) { + cleaned = true; + } + + if ( !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { + Output.get().log( "MineBomb %s: invalid mine name for prevented-Mines: %s Removed.", + LogLevel.WARNING, + bomb.getName(), cleanedMineName ); + cleaned = true; + } + else { + + mines.add(cleanedMineName); + } + + } + if ( cleaned ) { + bomb.setPreventedMines(mines); + isDirty = true; + } + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java index fd45845b1..14861671c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java @@ -16,9 +16,9 @@ public class MineBombsConfigData * data. *

*/ - public static final int MINE_BOMB_DATA_FORMAT_VERSION = 1; + public static final int MINE_BOMB_DATA_FORMAT_VERSION = 2; - private int dataFormatVersion = 1; + private int dataFormatVersion = 0; private Map bombs; diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java index 67b1d3664..0875b92ad 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java @@ -7,6 +7,7 @@ import java.util.SortedMap; import java.util.TreeMap; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; @@ -16,12 +17,19 @@ public class PlayerCache { - public static final String PLAYER_CACHE_WRITE_DELAY_CONFIG_NAME = "playercache.write_delay"; + public static final String PLAYER_CACHE_WRITE_DELAY_CONFIG_NAME = "player-cache.write-delay-sec"; + public static final int PLAYER_CACHE_WRITE_DELAY_VALUE_SEC = 60; // 60 seconds public static final long PLAYER_CACHE_WRITE_DELAY_VALUE_MS = 60000; // 60 seconds - public static final String PLAYER_CACHE_TIME_TO_LIVE_CONFIG_NAME = "playercache.time_to_live"; + public static final String PLAYER_CACHE_TIME_TO_LIVE_CONFIG_NAME = "player-cache.time-to-live-sec"; + public static final int PLAYER_CACHE_TIME_TO_LIVE_VALUE_SEC = 30 * 60; // 30 mins public static final long PLAYER_CACHE_TIME_TO_LIVE_VALUE_MS = 30 * 60 * 1000; // 30 mins + public static final String PLAYER_CACHE_UPDATE_PLAYER_STATS_CONFIG_NAME = "player-cache.update-player-stats-sec"; + public static final int PLAYER_CACHE_UPDATE_PLAYER_STATS_SEC = 30; // 30 Sec + + + private static PlayerCache instance; private PlayerCacheFiles cacheFiles; @@ -376,9 +384,13 @@ public PlayerCacheRunnable submitCacheRefresh() { PlayerCacheSaveAllPlayersTask task = new PlayerCacheSaveAllPlayersTask(); + long writeTimeTicks = Prison.get().getPlatform() + .getConfigInt( PLAYER_CACHE_WRITE_DELAY_CONFIG_NAME, + PLAYER_CACHE_WRITE_DELAY_VALUE_SEC ) * 20; + // Submit Timer Task to start running in 10 minutes (6000 ticks) and then // refresh stats every 5 minutes (3000 ticks): - int taskId = PrisonTaskSubmitter.runTaskTimerAsync( task, 6000, 3000 ); + int taskId = PrisonTaskSubmitter.runTaskTimerAsync( task, 6000, writeTimeTicks ); task.setTaskId( taskId ); return task; @@ -389,10 +401,14 @@ public PlayerCacheRunnable submitCacheUpdatePlayerStats() { PlayerCacheCheckTimersTask task = new PlayerCacheCheckTimersTask(); + int repeatTimeTicks = Prison.get().getPlatform() + .getConfigInt( PLAYER_CACHE_UPDATE_PLAYER_STATS_CONFIG_NAME, + PLAYER_CACHE_UPDATE_PLAYER_STATS_SEC ) * 20; + // Submit Timer Task to start running in 30 seconds (600 ticks) and then // refresh stats every 10 seconds (200 ticks). // This does not update any files or interacts with bukkit/spigot. - int taskId = PrisonTaskSubmitter.runTaskTimerAsync( task, 600, 200 ); + int taskId = PrisonTaskSubmitter.runTaskTimerAsync( task, 600, repeatTimeTicks ); task.setTaskId( taskId ); return task; diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java index 0dd418f35..6f6c0c32e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Set; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.output.Output; /** @@ -45,7 +46,7 @@ public class PlayerCacheSaveAllPlayersTask extends PlayerCacheRunnable { - public static long LAST_SEEN_INTERVAL_30_MINUTES = 30 * 60 * 1000; +// public static long LAST_SEEN_INTERVAL_30_MINUTES = 30 * 60 * 1000; @Override public void run() @@ -55,6 +56,12 @@ public void run() List purge = new ArrayList<>(); + + long lastSeenInterval = Prison.get().getPlatform().getConfigInt( + PlayerCache.PLAYER_CACHE_TIME_TO_LIVE_CONFIG_NAME, + PlayerCache.PLAYER_CACHE_TIME_TO_LIVE_VALUE_SEC + ); + Set keys = pCache.getPlayers().keySet(); for ( String key : keys ) @@ -74,7 +81,7 @@ public void run() (playerData.isDirty() || playerData.getLastSeenDate() == 0 || (System.currentTimeMillis() - playerData.getLastSeenDate()) - > LAST_SEEN_INTERVAL_30_MINUTES ) ) { + > lastSeenInterval ) ) { // Update the player's last seen date only when dirty and they // are online: playerData.setLastSeenDate( System.currentTimeMillis() ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonPasteChat.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonPasteChat.java index a88baaed2..7c0642ecd 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonPasteChat.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonPasteChat.java @@ -17,6 +17,9 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; +import nl.kyllian.enums.Expire; +import nl.kyllian.enums.PasteFormat; +import nl.kyllian.models.Paste; import tech.mcprison.prison.Prison; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Text; @@ -107,7 +110,24 @@ public String post( String text, boolean raw, boolean keepColorCodes ) { cleanedText = addHeaders( cleanedText ); - results = postPaste( cleanedText, raw ); + String service = Prison.get().getPlatform() + .getConfigString( "prison-support.submit-service", "PRIVATEBIN-NET" ); + + switch ( service ) { + case "PRIVATEBIN-NET": + + results = postPrivateBin( cleanedText, raw ); + break; + + case "PASTE-HELPCHAT": + + results = postPasteHelpchAt( cleanedText, raw ); + break; + + default: + break; + } + } catch (Exception e) { Output.get().logInfo( "PrisonPasteChat: Failed to paste to paste.helpch.at. " + @@ -215,8 +235,42 @@ private String padSpaces( String keyName ) { return (keyName + " ").substring( 0,18 ); } - private String postPaste( String text, boolean raw ) + + private String postPrivateBin( String text, boolean raw ) + throws IOException { + + String expire = Prison.get().getPlatform().getConfigString( "prison-support.expire", "one_week" ); + String password = Prison.get().getPlatform().getConfigString( "prison-support.password", "PrisonSupport" ); + + Paste paste = new Paste("https://privatebin.net") + .setMessage( text ) + .setExpire( getExpire( expire ) ) + .setPasteFormat( PasteFormat.PLAINTEXT ) + .setUserPassword( password ) +// .removeIps() + .encrypt(); + + String pasteUrl = paste.send(); + + return pasteUrl; + } + + private Expire getExpire( String value ) { + Expire results = Expire.ONE_WEEK; + + for ( Expire ex : Expire.values() ) { + if ( ex.name().equalsIgnoreCase( value ) ) { + results = ex; + break; + } + } + + return results; + } + + private String postPasteHelpchAt( String text, boolean raw ) throws IOException { + String results = null; String rawJson = null; @@ -249,8 +303,8 @@ private String postPaste( String text, boolean raw ) rawJson = reader.readLine(); } } - catch (IOException e) { - Output.get().logError( + catch (Exception e) { + Output.get().logWarn( String.format( "Failure in sending paste. %s ", e.getMessage()) , e ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFiles.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFiles.java new file mode 100644 index 000000000..e3bbc920b --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFiles.java @@ -0,0 +1,487 @@ +package tech.mcprison.prison.discord; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringReader; +import java.text.DecimalFormat; + +import tech.mcprison.prison.Prison; + +public class PrisonSupportFiles { + + public static final String PSFN_KEY__NAME = "{$name}"; + public static final String PSFN_KEY__NUMBER = "{$number}"; + public static final String PRISON_SUPPORT_FILE_NAME__PATTERN = "prison_support_" + + PSFN_KEY__NAME + "_" + PSFN_KEY__NUMBER + ".html"; + + public static final String SECTION_CODE = "§"; + + private File supportFile; + + private boolean colorMapping = true; + + public enum ColorMaps { + black( "&0", "", "" ), + DarkBlue( "&1", "", "" ), + DarkGreen( "&2", "", "" ), + DarkCyan( "&3", "", "" ), + DarkRed( "&4", "", "" ), + DarkMagenta( "&5", "", "" ), + Orange( "&6", "", "" ), + LightGray( "&7", "", "" ), + DarkGray( "&8", "", "" ), + + Blue( "&9", "", "" ), + Green( "&a", "", "" ), + Cyan( "&b", "", "" ), + Red( "&c", "", "" ), + Magenta( "&d", "", "" ), + Yellow( "&e", "", "" ), + White( "&f", "", "" ), + + + bold( "&l", "", "" ), + strike( "&m", "", "" ), + underline( "&n", "", "" ), + italic( "&o", "", "" ), + + reset( "&r", "", "" ), + + // Internal codes: + colorMappingOff( "&-", "", "" ), + colorMappingOn( "&+", "", "" ) + ; + + private final String colorCode; + private final String start; + private final String end; + private ColorMaps( String colorCode, String start, String end ) { + this.colorCode = colorCode; + this.start = start; + this.end = end; + } + public String getColorCode() { + return colorCode; + } + public String getStart() { + return start; + } + public String getEnd() { + return end; + } + + public static ColorMaps match( String line ) { + ColorMaps results = null; + + for (ColorMaps cm : values() ) { + + String cc1 = cm.getColorCode(); + String cc2 = cc1.replace("&", SECTION_CODE); + +// char test = line.charAt(0); +// char test2 = '\u0167'; +// +// String t = "Test: " + test + test2; +// +// String cc2 = cc1.replace("&", "§"); +// String cc3 = cc1.replace("&", "\u0167"); // Section code: §, § § § +// String cc4 = cc1.replace("&", Character.toString(test2) ); +// +// char test3 = cc2.charAt(0); + +// Character.getType( cc2.charAt(0)); +// Character. ( cc2.charAt(0)); + + if ( line.toLowerCase().startsWith( cc1 ) || line.startsWith( cc2 ) ) { + results = cm; + break; + } + } + + return results; + } + } + + + public File setupSupportFile( String name ) { + + String nameId = name.replaceAll("\\s", "_"); + File file = createSupportFile( nameId ); + + setSupportFile( file ); + + return getSupportFile(); + } + + public void saveToSupportFile( StringBuilder text, String supportName ) { + + File file = getSupportFile(); + + // If an empty file, then delete it: + if ( file.exists() && file.length() == 0 ) { + file.delete(); + } + + if ( !file.exists() ) { + saveSupportDataToFile( text, supportName ); + } + else { + appendSaveSupportDataToFile( text ); + } + + } + +// private void saveSupportDataToFile( StringBuilder text ) { +// File file = getSupportFile(); +// +// try { +// Files.write( text.toString().getBytes(), file); +// } +// catch (IOException e) { +// e.printStackTrace(); +// } +// } + + + private void saveSupportDataToFile( StringBuilder text, String supportName ) { + File file = getSupportFile(); + + try ( + BufferedWriter bw = new BufferedWriter( new FileWriter( file, false )); // create file + ) { + + + bw.write( getHtmlHead( supportName ) ); + bw.write( getHtmlBodyStart() ); + + writeBufferedWriter( bw, text ); + +// bw.write( getHtmlBodyEnd() ); + + } + catch (IOException e) { + e.printStackTrace(); + } + } + + private void appendSaveSupportDataToFile( StringBuilder text ) { + File file = getSupportFile(); + + try ( + BufferedWriter bw = new BufferedWriter( new FileWriter( file, true )); // append + ) { + + bw.write( "\n\n- = - = - = - = - = - = - = - = - = - = -\n\n"); + + writeBufferedWriter( bw, text ); +// bw.write( text.toString() ); + + } + catch (IOException e) { + e.printStackTrace(); + } + } + + + private void writeBufferedWriter( BufferedWriter bw, StringBuilder text ) { + + try ( + BufferedReader br = new BufferedReader( new StringReader( text.toString() )); + ) { + + String line = br.readLine(); + + while ( line != null ) { + + String converted = convertColorCodes( line ); + + bw.write(converted); + + line = br.readLine(); + } + + } + catch ( Exception e ) { + + } + } + + + protected String convertColorCodes(String line) { + StringBuilder sb = new StringBuilder(); + + if ( isColorMapping() ) { + + StringBuilder sbEnd = new StringBuilder(); + + for ( int i = 0; i < line.length(); i++ ) { + + int idx1 = line.indexOf(SECTION_CODE, i); + int idx2 = line.indexOf("&", i); + + int idx = smallestButValid( idx1, idx2 ); + + if ( idx == -1 ) { + sb.append( line.substring(i) ); + break; + } + + String left = line.substring(i, idx); + sb.append( left ); + + String right = line.substring(idx); + ColorMaps cm = ColorMaps.match( right ); + + if ( cm == null ) { + sb.append( line.substring(idx,idx+1)); + i = idx; + } +// else if ( cm == ColorMaps.colorMappingOn ) { +// +// setColorMapping( true ); +// sb.append( right.replace( cm.getColorCode(), "" ) ); +// break; +// } +// else if ( !isColorMapping() ) { +// i = idx + 1; +// } + else if ( cm == ColorMaps.colorMappingOff ) { + + setColorMapping( false ); + sb.append( right.replace( cm.getColorCode(), "" ) ); + break; + } + else if ( cm == ColorMaps.reset ) { + sb.append( sbEnd ); + sbEnd.setLength(0); + i = idx + 1; + } + else { + sb.append( cm.getStart() ); + sbEnd.insert(0, cm.getEnd() ); + i = idx + 1; + } + + } + + sb.append( sbEnd ) + .append( "\n"); + } + else { + ColorMaps cm = ColorMaps.match( line ); + + // ignore all other maps... since color mapping is off, we can only search for ON: + if ( cm == ColorMaps.colorMappingOn ) { + setColorMapping( true ); + + // Return the line without the color code: + sb.append( line.replace( cm.getColorCode(), "" ) ) + .append( "\n"); + } + else { + sb.append( line ) + .append( "\n"); + + } + } + + return sb.toString(); + } + + private int smallestButValid(int idx1, int idx2) { + + int results = idx1 != -1 ? idx1 : -1; + + if ( results == -1 || idx2 != -1 && idx2 < results ) { + results = idx2; + } + + return results; + } + + public String getFileStats( long addedContentSize ) { + StringBuilder sb = new StringBuilder(); + + DecimalFormat dFmt = new DecimalFormat( "#,##0.000" ); + + double fileSize = getSupportFile().length() / 1024d; + + double newDataSize = addedContentSize / 1024d; + + sb.append( " * " ) + .append( getSupportFile().getAbsolutePath() ) + .append( " " ) + .append( dFmt.format(fileSize) ) + .append( " KB Before HTML conversion: " ) + .append( dFmt.format(newDataSize) ) + .append( " KB"); + + return sb.toString(); + } + + + private File createSupportFile( File dir, String name ) { + File file = null; + + DecimalFormat iFmt = new DecimalFormat( "0000" ); + + for ( int i = 0; i < 1000; i++ ) { + String fileName = PRISON_SUPPORT_FILE_NAME__PATTERN + .replace( PSFN_KEY__NAME, name ) + .replace( PSFN_KEY__NUMBER, iFmt.format( i ) ); + + file = new File( dir, fileName ); + if ( !file.exists() ) { + break; + } + } + return file; + } + + private File createSupportFile( String name ) { + File dir = new File( Prison.get().getDataFolder(), "backups" ); + + File file = createSupportFile( dir, name ); + +// File[] files = dir.listFiles( new FilenameFilter() { +// public boolean accept( File dir, String fileName ) { +// return fileName.startsWith("prison_support_") && +// fileName.endsWith(".md"); +// } +// }); + + return file; + } + + private String getHtmlHead( String supportName ) { + StringBuilder sb = new StringBuilder(); + + sb.append( "\n" ) + .append( "\n" ) + .append( "\n" ) + .append( "Prison Support: " ) + .append( supportName ) + .append( "\n" ) + .append( " \n" ) + .append( getGlobalCss() ) + .append( "\n" ); + + return sb.toString(); + } + + private String getHtmlBodyStart() { + StringBuilder sb = new StringBuilder(); + + sb.append( "\n"); + sb.append( "
\n"); + sb.append( " "); + sb.append( "\n"); + sb.append( "
\n"); + + return sb.toString(); + } + + @SuppressWarnings("unused") + private String getHtmlBodyEnd() { + StringBuilder sb = new StringBuilder(); + + sb.append( "\n" ); + sb.append( "\n" ); + + return sb.toString(); + } + + private String getGlobalCss() { + StringBuilder sb = new StringBuilder(); + + sb.append( "" ); + + return sb.toString(); + } + + public File getSupportFile() { + return supportFile; + } + public void setSupportFile(File supportFile) { + this.supportFile = supportFile; + } + + public boolean isColorMapping() { + return colorMapping; + } + public void setColorMapping(boolean colorMapping) { + this.colorMapping = colorMapping; + } + + +} 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 55e23a387..b2deb33dc 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 @@ -89,6 +89,13 @@ private static String getFileNamePrefix( String UUIDString ) { return UUIDString.substring( 0, 14 ); } + + public String toString( Object obj ) { + String json = getGson().toJson( obj ); + + return json; + } + /** * This function will save a file as a JSON format. It will first save it as a * temp file to make sure the data can be written to the file system, then once diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/Block.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/Block.java index 5e166a0cf..df65f516f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/Block.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/Block.java @@ -121,4 +121,41 @@ default boolean isEmpty() { public void setBlockName( String blockName ); + /** + *

The sale price is the amount that is paid to the player when they + * sell their items. A null indicates that no price was set. + *

+ * + * @return + */ + public Double getSalePrice(); + + /** + *

The sale price is the amount that is paid to the player when they + * sell their items. A null indicates that no price was set. + *

+ * + * @param price + */ + public void setSalePrice( Double price ); + + /** + *

The purchase price is what player pays to purchase the items. + * A null indicates that no price was set. + *

+ * + * @return + */ + public Double getPurchasePrice(); + + /** + *

The purchase price is what player pays to purchase the items., + * A null indicates that no price was set. + *

+ * + * @param price + */ + public void setPurchasePrice( Double price ); + + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java index bb38a8643..d4218f223 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java @@ -5,5 +5,23 @@ public enum MineResetType normal, // paged, clear, - tracer; + tracer, + corners, + outline; + + public static MineResetType fromString( String resetType ) { + MineResetType results = normal; + + if ( resetType != null ) { + + for (MineResetType mrt : values() ) { + if ( mrt.name().equalsIgnoreCase( resetType ) ) { + results = mrt; + break; + } + } + } + + return results; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index 91cc4dd59..7af56bcf7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -12,6 +12,7 @@ public class MineTargetPrisonBlock private boolean airBroke; private boolean isEdge; + private boolean isCorner; private boolean exploded; private boolean mined = false; @@ -26,7 +27,9 @@ public class MineTargetPrisonBlock public MineTargetPrisonBlock( PrisonBlockStatusData prisonBlock, World world, - int x, int y, int z, boolean isEdge ) { + int x, int y, int z, + boolean isEdge, + boolean isCorner ) { this.blockKey = new MineTargetBlockKey( world, x, y, z ); this.prisonBlock = prisonBlock; @@ -36,6 +39,7 @@ public MineTargetPrisonBlock( } this.isEdge = isEdge; + this.isCorner = isCorner; } @Override @@ -48,13 +52,26 @@ public PrisonBlock getPrisonBlock( MineResetType resetType ) { final PrisonBlock pBlock; - if ( resetType == MineResetType.tracer && isEdge() ) + if ( ( resetType == MineResetType.tracer || + resetType == MineResetType.outline ) && isEdge() ) { + // Generates the tracer along all edges of the mine + // NOTE: outline and tracer are the same. Outline should be + // converted to tracer, but if it's not, then handle it here + pBlock = PrisonBlock.PINK_STAINED_GLASS; + } + else if ( resetType == MineResetType.corners && isCorner() ) + { + // Generates the trace along all the corners of the mine pBlock = PrisonBlock.PINK_STAINED_GLASS; } else if ( resetType == MineResetType.clear || - resetType == MineResetType.tracer ) + resetType == MineResetType.tracer || + resetType == MineResetType.outline || + resetType == MineResetType.corners ) { + // clears the mine with all AIR, or for tracers the non edges, + // or clears all of the mine except the corners. pBlock = PrisonBlock.AIR; } else if ( getPrisonBlock() != null && @@ -125,6 +142,13 @@ public void setEdge( boolean isEdge ) { this.isEdge = isEdge; } + public boolean isCorner() { + return isCorner; + } + public void setCorner(boolean isCorner) { + this.isCorner = isCorner; + } + public boolean isExploded() { return exploded; } 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 70215ca7b..2f997747a 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 @@ -43,6 +43,10 @@ public class PrisonBlock private Location location = null; + private Double salePrice = null; + private Double purchasePrice = null; + + static { AIR = new PrisonBlock( InternalBlockTypes.AIR.name(), false ); GLASS = new PrisonBlock( InternalBlockTypes.GLASS.name(), true ); @@ -285,6 +289,52 @@ public void setLocation( Location location ) { this.location = location; } + + /** + *

The sale price is the amount that is paid to the player when they + * sell their items. A null indicates that no price was set. + *

+ * + * @return + */ + public Double getSalePrice() { + return salePrice; + } + + /** + *

The sale price is the amount that is paid to the player when they + * sell their items. A null indicates that no price was set. + *

+ * + * @param price + */ + public void setSalePrice( Double price ) { + this.salePrice = price; + } + + /** + *

The purchase price is what player pays to purchase the items. + * A null indicates that no price was set. + *

+ * + * @return + */ + public Double getPurchasePrice() { + return purchasePrice; + } + + /** + *

The purchase price is what player pays to purchase the items., + * A null indicates that no price was set. + *

+ * + * @param price + */ + public void setPurchasePrice( Double price ) { + this.purchasePrice = price; + } + + public PrisonBlock clone() { return new PrisonBlock( this ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/inventory/PlayerInventory.java b/prison-core/src/main/java/tech/mcprison/prison/internal/inventory/PlayerInventory.java index 723b4b11d..b8d4ab439 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/inventory/PlayerInventory.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/inventory/PlayerInventory.java @@ -28,6 +28,14 @@ */ public interface PlayerInventory extends Inventory { + + public ItemStack[] getContents(); + public void setContents( ItemStack[] items ); + + public ItemStack[] getExtraContents(); + public void setExtraContents( ItemStack[] items ); + + /** * Gets the armor this player is wearing * 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 479f4be6d..d0ac90ea1 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 @@ -303,6 +303,15 @@ public default Optional getCommand(String label) { public double getConfigDouble( String key, double defaultValue ); + /** + *

Given the path to a hash, this will return all of the keys within + * the hash at the root level. It will not traverse deeper. + * The list of keys can then be used to access all of the values. + *

+ * + */ + public List getConfigHashKeys(String hashPrefix); + public boolean isWorldExcluded( String worldName ); @@ -379,6 +388,8 @@ public void autoCreateMineLinerAssignment( List rankMineNames, public void saveResource( String string, boolean replace ); + + public boolean isMineNameValid(String mineName); public String getMinesListString(); @@ -435,7 +446,7 @@ public void autoCreateMineLinerAssignment( List rankMineNames, public TreeSet getExcludedWorlds(); - public List getConfigStringArray( String key ); + public List getConfigStringArray( String key ); public int compareServerVerisonTo( String comparisonVersion ); @@ -460,4 +471,10 @@ public void autoCreateMineLinerAssignment( List rankMineNames, public int getMaxY(); + + public String getLadderByFileName(String name); + + + public String getRankByFileName(String name); + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java b/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java index bdf29f826..c8c6f1181 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java @@ -83,6 +83,8 @@ public class LocaleManager { private static final String DEFAULT_LOCALE = "en_US"; private static final String LOCALE_FOLDER = "lang"; + public static final String IGNORE_TEXT_NO_MESSAGE_INTENDED = "*none*"; + public static final String LOCALE_ERROR__CONFIG_LANG_NOT_FOUND = "local.error.configNotFound"; public static final String LOCALE_ERROR__FALLBACK_COUNT = "local.error.fallbackcount"; @@ -115,6 +117,13 @@ public class LocaleManager { ALTERNATIVES.put("pt_PT", Arrays.asList("pt_BR", "en_US")); ALTERNATIVES.put("ro_RO", Arrays.asList("en_US")); + + // Chinese dialects + ALTERNATIVES.put("zh_TW", Arrays.asList("zh_TW", "en_US")); + ALTERNATIVES.put("zh_CN", Arrays.asList("zh_CN", "en_US")); + // NOTE: many files are named with "-" dash and not underscore... so have both settings + ALTERNATIVES.put("zh-CN", Arrays.asList("zh-CN", "en_US")); + } private final PluginEntity module; @@ -702,6 +711,11 @@ private void loadLocale(String name, InputStream is, boolean printStackTrace) { String[] keyValue = line.split( "\\=" ); String value = (keyValue.length > 1 ? keyValue[1] : ""); // StringEscapeUtils.escapeJava( keyValue[1] ); + +// if ( IGNORE_TEXT_NO_MESSAGE_INTENDED.equalsIgnoreCase(value) ) { +// value = ""; +// } + temp.put( keyValue[0], value ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/localization/Localizable.java b/prison-core/src/main/java/tech/mcprison/prison/localization/Localizable.java index ca25eec0c..cd0504a27 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/localization/Localizable.java +++ b/prison-core/src/main/java/tech/mcprison/prison/localization/Localizable.java @@ -245,6 +245,13 @@ private String localizeIn(String locale, boolean recursive, String... fallbacks) Properties props = getParent().getConfigs().get(locale); if (props.containsKey(getKey())) { // check if the message is defined in the locale String message = (String) props.get(getKey()); // yay, it worked + + // If the entry has been marked with "*none*" or an empty String then return an empty String: + if ( LocaleManager.IGNORE_TEXT_NO_MESSAGE_INTENDED.equalsIgnoreCase(message) || + message != null && message.trim().length() == 0 ) { + return ""; + } + if (replacements != null) { for (int i = 0; i < replacements.length; i++) { // replace placeholder sequences message = message @@ -380,7 +387,12 @@ public void sendTo(CommandSender sender, LogLevel level) { * @param sender The {@link CommandSender} to send this {@link Localizable} to */ public void sendTo(CommandSender sender) { - sendTo(sender, LogLevel.PLAIN); + + String message = localize(); + if ( message != null && !message.isEmpty() ) { + + sendTo(sender, LogLevel.PLAIN); + } } /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleManager.java b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleManager.java index 73b8c6d15..532424f75 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleManager.java @@ -37,6 +37,9 @@ public class ModuleManager { public static final String MODULE_MANAGER_DIRECTORY = "module_conf"; + public static final String MODULE_NAME_MINES = "Mines"; + public static final String MODULE_NAME_RANKS = "Ranks"; + private List modules; private List disabledModules; private File moduleRoot; @@ -48,6 +51,14 @@ public ModuleManager() { moduleRoot = getModuleRootDefault(); } + + public boolean isEnabled( String moduleName ) { + + Module module = getModule( moduleName ); + + return module != null && module.isEnabled(); + } + public static File getModuleRootDefault() { File moduleRoot = new File(PrisonAPI.getPluginDirectory(), MODULE_MANAGER_DIRECTORY); if (!moduleRoot.exists()) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/ChatDisplay.java b/prison-core/src/main/java/tech/mcprison/prison/output/ChatDisplay.java index 05e938e08..306300843 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/ChatDisplay.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/ChatDisplay.java @@ -152,5 +152,60 @@ public boolean isShowTitle() { public void setShowTitle(boolean showTitle) { this.showTitle = showTitle; } + + /** + *

This adds a hyperLink data element to the ChatDisplay. + * A hyperLink data element consist of 2 or 3 words, and no actual linkage. The hyperlinks + * will be auto generated when the support document is generated. + *

+ * + *

The proper format is for the first word to identify the major grouping, such as + * `Mine`, `Rank`, `Ladder`, or `Commands`. + *

+ * + *

The second word must be the name of the mine, rank, or ladder. For mines, ranks, and + * ladders, the second word can also be a type of groupings of such mines, rnaks, and ladders, + * such as `TOC`, `List`, etc... + * For commands, the second word must be the name of the command's config file. + *

+ * + *

The third word is used to qualify the type of item, for example for config files, the + * third world would always be `File` since it carries a special format where the contents + * do not have the color mappings rendered. Also, for some major groupings, like `Ladder List`, + * it also needs a qualifying ladder name as the third word since there are multiple + * ladders, each is a group of ranks, but there is also just a list of + * all ladders, as found in `Ladder List`. For example, `Ladder List default`, or + * `Ladder List donors`, with also `Ladder List`. + *

+ * + *

This structure is used to auto generate html tag IDs and also their related links + * to other content. + *

+ * + *

For example, let's assume we have one entry for `Rank B`. This will crate an ID for that + * section of something like `` Then it will also create hyperlinks + * to `(TOC)` `(Rank List)` `(Rank B File)`. These hyperlinks will then generat it's own ID, with + * hyperlinks to the other related content. This will allow fast and simple way to + * jump to the various components of data that is related to this concerpt of Rank B. + *

+ * + *

The data that is passed to this function should just be plain names. But the actual + * content is wrapped with double pipes. So if the data `Rank B` is passed to this function, + * it would be stored as `||Rank B||`. This notation is used to identify that it is a + * support hyperlink, so all supporting hyperlinks can be generated from this data. + *

+ * + *

This data will never be shown to players in game, or shown within the console. + * This is only included in the Prison Support documents to better utilize the + * support teams time and talents. + *

+ * + * @param linkData + */ + public void addSupportHyperLinkData( String linkData, Object... args ) { + String codedLinkData = "||" + linkData + "||"; + SupportHyperLinkComponent shlc = new SupportHyperLinkComponent( codedLinkData, args ); + addComponent( shlc ); + } } 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 7b19517d0..85b5ef47d 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 @@ -28,6 +28,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.internal.Player; /** * Standardized output to the console and to players. @@ -40,6 +41,8 @@ public class Output public static final String PERCENT_ENCODING = "%"; public static final String PERCENT_DECODING = "%"; + public static final String LINE_SPLITING = "\\{br\\}"; +// public static final String LINE_SPLITING = "\n"; private static Output instance; @@ -52,10 +55,10 @@ public class Output private String prefixTemplateError; private String prefixTemplateDebug; - private String colorCodeInfo; - private String colorCodeWarning; - private String colorCodeError; - private String colorCodeDebug; + private final String colorCodeInfo; + private final String colorCodeWarning; + private final String colorCodeError; + private final String colorCodeDebug; private boolean debug = false; @@ -63,6 +66,8 @@ public class Output private Set selectiveDebugTargets; private int debugCountDown = -1; + + private String debugPlayerName = null; public enum DebugTarget { all, @@ -279,10 +284,17 @@ else if ( Prison.get() == null || Prison.get().getPlatform() == null ) { // msg = msg.replace( PERCENT_ENCODING, PERCENT_DECODING ); // } - Prison.get().getPlatform().log( - prefixTemplatePrison + " " + - getLogColorCode(level) + - msg); + String msgRaw = String.format(msg, args); + boolean includePrefix = true; + for (String msgSplit : msgRaw.split( LINE_SPLITING )) { + + Prison.get().getPlatform().log( + (includePrefix ? (prefixTemplatePrison + " ") : "") + + getLogColorCode(level) + + msgSplit); + includePrefix = false; + } + } catch ( MissingFormatArgumentException e ) { @@ -365,24 +377,45 @@ public void logError(String message, Throwable... throwable) { } public void logDebug(String message, Object... args) { + logDebug( message, null, args ); + } + public void logDebug(String message, Player player, Object... args) { if ( isDebug() ) { - if ( debugCountDown != -1 && debugCountDown-- == 1 ) { - setDebugCountDown( -1 ); - setDebug( false ); + + if ( getDebugPlayerName() == null || + getDebugPlayerName() != null && player != null && + getDebugPlayerName().equalsIgnoreCase( player.getName() ) ) { + + if ( debugCountDown != -1 && debugCountDown-- == 1 ) { + setDebugCountDown( -1 ); + setDebug( false ); + setDebugPlayerName( null ); + } + log(message, LogLevel.DEBUG, args); } - log(message, LogLevel.DEBUG, args); } } public void logDebug( DebugTarget debugTarget, String message, Object... args) { + logDebug( debugTarget, message, null, args ); + } + + public void logDebug( DebugTarget debugTarget, String message, Player player, Object... args) { if ( isDebug( debugTarget ) ) { - if ( debugCountDown != -1 && debugCountDown-- == 1 ) { - setDebugCountDown( -1 ); - setDebug( false ); - } - log(message, LogLevel.DEBUG, args); + + if ( getDebugPlayerName() == null || + getDebugPlayerName() != null && player != null && + getDebugPlayerName().equalsIgnoreCase( player.getName() ) ) { + + if ( debugCountDown != -1 && debugCountDown-- == 1 ) { + setDebugCountDown( -1 ); + setDebug( false ); + setDebugPlayerName( null ); + } + log(message, LogLevel.DEBUG, args); // logDebug(message, args ); + } } // // The following is not yet enabled since the user interfaces are not in place to manage the set: @@ -430,6 +463,9 @@ public void applyDebugTargets( String targets ) { setDebugCountDown( -1 ); setDebug( false ); + // If turning off debug mode, then reset only-for-player name to null: + setDebugPlayerName( null ); + log( "Prison Debugger Disabled: Count down timer is disabled: %d", LogLevel.DEBUG, countDownNumber ); return; } @@ -460,9 +496,17 @@ public void applyDebugTargets( String targets ) { // No targets were set, so just toggle the debugger: Output.get().setDebug( !Output.get().isDebug() ); + // Clear all existing targets: getActiveDebugTargets().clear(); + + // If turning off debug mode, then reset only-for-player name to null: + if ( !isDebug() ) { + setDebugPlayerName( null ); + } + + // Turn off the countdown timer if it was set (not -1): if ( !isDebug() && getDebugCountDown() != -1 ) { setDebugCountDown( -1 ); @@ -578,7 +622,11 @@ public void sendMessage(CommandSender sender, String message, LogLevel level, Ob if ( level == null ) { level = LogLevel.PLAIN; } - sender.sendMessage(getLogPrefix(level) + String.format(message, args)); + String msgRaw = String.format(message, args); + for (String msg : msgRaw.split( LINE_SPLITING )) { + + sender.sendMessage(getLogPrefix(level) + msg); + } } } @@ -622,4 +670,29 @@ private String gen(String name) { return String.format(prefixTemplate, name); } + + public String getColorCodeInfo() { + return colorCodeInfo; + } + + public String getColorCodeWarning() { + return colorCodeWarning; + } + + public String getColorCodeError() { + return colorCodeError; + } + + public String getColorCodeDebug() { + return colorCodeDebug; + } + + + public String getDebugPlayerName() { + return debugPlayerName; + } + public void setDebugPlayerName(String debugPlayerName) { + this.debugPlayerName = debugPlayerName; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/SupportHyperLinkComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/SupportHyperLinkComponent.java new file mode 100644 index 000000000..61b938d4a --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/output/SupportHyperLinkComponent.java @@ -0,0 +1,79 @@ +package tech.mcprison.prison.output; + +import tech.mcprison.prison.internal.CommandSender; + +/** + *

This adds a hyperLink data element to the ChatDisplay. + * A hyperLink data element consist of 2 or 3 words, and no actual linkage. The hyperlinks + * will be auto generated when the support document is generated. + *

+ * + *

This information applies to this data type, which is also part of the constructor + * with parameters. + *

+ * + *

The proper format is for the first word to identify the major grouping, such as + * `Mine`, `Rank`, `Ladder`, or `Commands`. + *

+ * + *

The second word must be the name of the mine, rank, or ladder. For mines, ranks, and + * ladders, the second word can also be a type of groupings of such mines, rnaks, and ladders, + * such as `TOC`, `List`, etc... + * For commands, the second word must be the name of the command's config file. + *

+ * + *

The third word is used to qualify the type of item, for example for config files, the + * third world would always be `File` since it carries a special format where the contents + * do not have the color mappings rendered. Also, for some major groupings, like `Ladder List`, + * it also needs a qualifying ladder name as the third word since there are multiple + * ladders, each is a group of ranks, but there is also just a list of + * all ladders, as found in `Ladder List`. For example, `Ladder List default`, or + * `Ladder List donors`, with also `Ladder List`. + *

+ * + *

This structure is used to auto generate html tag IDs and also their related links + * to other content. + *

+ * + *

For example, let's assume we have one entry for `Rank B`. This will crate an ID for that + * section of something like `` Then it will also create hyperlinks + * to `(TOC)` `(Rank List)` `(Rank B File)`. These hyperlinks will then generat it's own ID, with + * hyperlinks to the other related content. This will allow fast and simple way to + * jump to the various components of data that is related to this concerpt of Rank B. + *

+ * + *

The data that is passed to this function should just be plain names. But the actual + * content is wrapped with double pipes. So if the data `Rank B` is passed to this function, + * it would be stored as `||Rank B||`. This notation is used to identify that it is a + * support hyperlink, so all supporting hyperlinks can be generated from this data. + *

+ * + *

This data will never be shown to players in game, or shown within the console. + * This is only included in the Prison Support documents to better utilize the + * support teams time and talents. + *

+ * + * + * + * @author Blue + * + */ +public class SupportHyperLinkComponent + extends DisplayComponent { + + protected String text; + + public SupportHyperLinkComponent(String text, Object... args) { + this.text = Output.stringFormat(text, args); + } + + @Override public String text() { + return text; + } + + @Override public void send(CommandSender sender) { + + // Do not send this message to the player... it is only for support documents: + //sender.sendMessage(text()); + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttribute.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttribute.java index 8fdfd9137..264c7baaf 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttribute.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttribute.java @@ -4,4 +4,7 @@ public interface PlaceholderAttribute { public String format( String value ); + public String getPlayer(); + + public void setPlayer( String player ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeBar.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeBar.java index 29e77c688..b3602f68d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeBar.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeBar.java @@ -61,6 +61,8 @@ public class PlaceholderAttributeBar private boolean hex2 = false; private boolean debug = false; + private String player = null; + public PlaceholderAttributeBar(ArrayList parts, PlaceholderProgressBarConfig defaultBarConfig, String raw ) { super(); @@ -77,6 +79,22 @@ public PlaceholderAttributeBar(ArrayList parts, boolean isReversed = parts.remove( "reverse" ); + + // Search for 'player=': + for (String part : parts) { + if ( part.toLowerCase().startsWith( "player=" ) ) { + this.player = part; + break; + } + } + // extract the player's name: + if ( this.player != null ) { + if ( parts.remove( this.player ) ) { + this.player = this.player.toLowerCase().replaceAll("player=", ""); + } + } + + int len = 1; // format: @@ -184,6 +202,13 @@ public void setDebug( boolean debug ) { this.debug = debug; } + public String getPlayer() { + return player; + } + public void setPlayer(String player) { + this.player = player; + } + public PlaceholderProgressBarConfig getBarConfig() { return barConfig; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeNumberFormat.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeNumberFormat.java index 73c163e36..023e5e733 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeNumberFormat.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeNumberFormat.java @@ -19,7 +19,7 @@ * *

Usage: *

- *
::nFormat:format:spaces:unitType:hex:hex2:debug
+ *
::nFormat:format:spaces:unitType:hex:hex2:debug:player=<playerName>
* *
    *
  • nFormat: the keyword to identify this attribute.
  • @@ -66,6 +66,10 @@ * will log to the console the status of this attribute, along with * any error messages that may occur when applying the attribute. * + *
  • player=<playerName>: Optional. Case insensitive. Non-positional; can be + * placed anywhere. Provides a player for the placeholder when the + * plugin requesting the placeholder cannot request it based upon the player. + *
  • *
* * @@ -86,6 +90,9 @@ public class PlaceholderAttributeNumberFormat private boolean hex2 = false; private boolean debug = false; + private String player = null; + + public PlaceholderAttributeNumberFormat( ArrayList parts, String raw ) { super(); @@ -99,6 +106,21 @@ public PlaceholderAttributeNumberFormat( ArrayList parts, String raw ) { this.hex2 = parts.remove( "hex2" ); this.debug = parts.remove( "debug" ); + // Search for 'player=': + for (String part : parts) { + if ( part.toLowerCase().startsWith( "player=" ) ) { + this.player = part; + break; + } + } + // extract the player's name: + if ( this.player != null ) { + if ( parts.remove( this.player ) ) { + this.player = this.player.toLowerCase().replaceAll("player=", ""); + } + } + + int len = 1; // format: @@ -310,4 +332,11 @@ public void setDebug( boolean debug ) { this.debug = debug; } + public String getPlayer() { + return player; + } + public void setPlayer(String player) { + this.player = player; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeText.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeText.java index 919493408..06d75ed15 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeText.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeText.java @@ -18,7 +18,7 @@ * *

Usage: *

- *
::text:hex:hex1:debug
+ *
::text:hex:hex1:debug:player=<playerName>
* *
    *
  • hex: Optional. Case sensitive. Non-positional; can be placed anywhere. @@ -37,6 +37,10 @@ * will log to the console the status of this attribute, along with * any error messages that may occur when applying the attribute. *
  • + *
  • player=<playerName>: Optional. Case insensitive. Non-positional; can be + * placed anywhere. Provides a player for the placeholder when the + * plugin requesting the placeholder cannot request it based upon the player. + *
  • *
* * @@ -52,6 +56,8 @@ public class PlaceholderAttributeText private boolean hex2 = false; private boolean debug = false; + private String player = null; + public PlaceholderAttributeText( ArrayList parts, String raw ) { super(); @@ -65,6 +71,22 @@ public PlaceholderAttributeText( ArrayList parts, String raw ) { this.hex2 = parts.remove( "hex2" ); this.debug = parts.remove( "debug" ); + + // Search for 'player=': + for (String part : parts) { + if ( part.toLowerCase().startsWith( "player=" ) ) { + this.player = part; + break; + } + } + // extract the player's name: + if ( this.player != null ) { + if ( parts.remove( this.player ) ) { + this.player = this.player.toLowerCase().replaceAll("player=", ""); + } + } + + } @@ -132,5 +154,11 @@ public void setDebug( boolean debug ) { this.debug = debug; } + public String getPlayer() { + return player; + } + public void setPlayer(String player) { + this.player = player; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeTime.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeTime.java new file mode 100644 index 000000000..b96edc9c4 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeTime.java @@ -0,0 +1,253 @@ +package tech.mcprison.prison.placeholders; + +import java.text.DecimalFormat; +import java.util.ArrayList; + +import org.apache.commons.lang3.StringUtils; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.placeholders.PlaceholderManager.NumberTransformationUnitTypes; +import tech.mcprison.prison.placeholders.PlaceholderManager.TimeTransformationUnitTypes; +import tech.mcprison.prison.util.Text; + +/** + *

This takes the placeholder attribute for time formatting + * and parses the dynamic content to setup this instance. + * Then this class applies the formatting to the generated placeholder + * results to produce the requested output. + *

+ * + *

Usage: + *

+ *
::time:spaces:unitType:hex:hex2:debug:player=
+ * + *

NOTE: 'format' is not used, so just collapse it and provide nothing as shown here. + * If any value is provided, it will be ignored. + *

::nFormat::spaces:unitType:hex:hex2:debug:player=
+ * + *
    + *
  • time: the keyword to identify this attribute.
  • + * + *
  • spaces: number of spaces between format and unit of measure. + * Optional. Defaults to 1.
  • + *
  • unitType: unit type to display or to use to transform the results. + * Optional. Defaults to 'long'. The control of these values + * can be found in the core language files. + * + *
      + *
    • long: Uses the long form of time and date units. Uses both the + * 'core_text__time_units_singular' and + * 'core_text__time_units_plural' language file settings.
    • + *
    • short: Uses the short form of time and date units. These are + * generally a single character each. Uses the + * 'core_text__time_units_short' language file settings.
    • + *
    • colons: Uses colons for the units, except for year, month, + * and week, it uses the same settings as found in the + * 'short' unit
    • + *
    + *
  • + * + *
  • hex: Optional. Case sensitive. Non-positional; can be placed anywhere. + * Only valid value is "hex". When enabled it will translate + * hex color codes, and other color codes before sending the placeholder + * results back to the requestor. This is useful for plugins that + * do not directly support hex color codes. + *
  • hex2: Optional. Case sensitive. Non-positional; can be placed anywhere. + * Only valid value is "hex2". When enabled it will translate + * hex color codes to their intermediate state, which uses '&' color + * codes, sending the placeholder results back to the requestor. + * This is useful for plugins that do not directly support hex + * color codes and may work when 'hex' does not. + *
  • debug: Optional. Case sensitive. Non-positional; can be placed anywhere. + * Only valid value is "debug". When enabled it + * will log to the console the status of this attribute, along with + * any error messages that may occur when applying the attribute. + *
  • + *
  • player=<playerName>: Optional. Case insensitive. Non-positional; can be + * placed anywhere. Provides a player for the placeholder when the + * plugin requesting the placeholder cannot request it based upon the player. + *
  • + *
+ * + * + */ +public class PlaceholderAttributeTime + extends PlaceholderAttributeNumberFormat { + + private TimeTransformationUnitTypes timeUnitType; + +// private ArrayList parts; +// private String raw; +// +// private boolean hex = false; +// private boolean hex2 = false; +// private boolean debug = false; +// +// private String player = null; + + + /** + *

The constructor parameters are exactly the same as the nFormat. + *

+ * + * @param parts + * @param raw + */ + public PlaceholderAttributeTime( ArrayList parts, String raw ) { + super( parts, raw); + + + // Override the unitType: + + // unitType: + String unitTypeStr = parts.size() > 3 ? parts.get( 3 ) : null; + TimeTransformationUnitTypes timeUnitType = + TimeTransformationUnitTypes.fromString( unitTypeStr ); + + setTimeUnitType( timeUnitType ); + + } + + @Override + public String format(Long value) { + String results = null; + + String spaces = StringUtils.repeat( " ", getSpaces() ); + + try { + // & will not work in the DecimalFormat so replace it with ^|^ then replace after formatting: + //String fmt = getFormat();//.replace( "&", "^|^" ); + //DecimalFormat dFmt = Prison.get().getDecimalFormat( fmt ); + + switch ( getTimeUnitType() ) + { + case none: + + results = PlaceholdersUtil.formattedTime( value ); + break; + + case LONG: + results = PlaceholdersUtil.formattedTime( value, spaces ); + break; + + case SHORT: + results = PlaceholdersUtil.formattedShortTime( value, spaces ); + break; + + case colons: + results = PlaceholdersUtil.formattedColonsTime( value, spaces ); + break; + + default: + break; + } + +// if ( results.contains( "^|^" ) ) { +// //results = results.replace( "^|^", "&" ); +// } + + } + catch (Exception e ) { + // Ignore unless in debug mode: + if ( isDebug() ) { + Output.get().logError( + String.format( "Error formatting results. long value= %s " + + "spaces=%d timeUnitType= %s ERRROR: %s", + + Double.toString( value ), getSpaces(), + getTimeUnitType(), e.getMessage() + )); + } + } + + + if ( isHex2() ) { + results = Text.translateAmpColorCodesAltHexCode( results ); + } + else if ( isHex() ) { + results = Text.translateAmpColorCodes( results ); + } + + if ( isDebug() ) { + String rawResults = Text.escapeAmpCodes(results); + String rawAttribute = Text.escapeAmpCodes(getRaw()); + + String message = String.format( "Placeholder Attribute time: double value= %s " + + "spaces=%d timeUnitType=%s Results: [%s] " + + "raw: &3[&7%s&3] &3[&7%s&3]" + + "(remove :debug from placeholder to disable this message)", + + Double.toString( value ), getSpaces(), + getTimeUnitType(), results, rawResults, rawAttribute + ); + Output.get().logInfo( message ); + } + + return results; + + } + + /** + * Not used. + */ + @Override + public String format(String value) { + String results = null; + + try { + long lValue = Long.parseLong( value ); + results = format( lValue ); + } + catch (Exception e ) { + // Ignore unless in debug mode: + if ( isDebug() ) { + Output.get().logError( + String.format( "Error parsing value to a long. String value= [%s] " + + "spaces=%d timeUnitType= %s ERRROR: %s", + + value, getSpaces(), + getTimeUnitType(), e.getMessage() + )); + } + } + + return results; + } + + + + @Override + public String format(Double value) { + String results = null; + + try { + long lValue = value.longValue(); + + results = format( lValue ); + } + catch (Exception e ) { + // Ignore unless in debug mode: + if ( isDebug() ) { + Output.get().logError( + String.format( "Error parsing value to a long. String value= [%s] " + + "spaces=%d timeUnitType= %s ERRROR: %s", + + value, getSpaces(), + getTimeUnitType(), e.getMessage() + )); + } + } + + return results; + } + + public TimeTransformationUnitTypes getTimeUnitType() { + return timeUnitType; + } + public void setTimeUnitType(TimeTransformationUnitTypes timeUnitType) { + this.timeUnitType = timeUnitType; + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderIdentifier.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderIdentifier.java index 1d48eee65..a9409b9d4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderIdentifier.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderIdentifier.java @@ -167,6 +167,14 @@ public boolean checkPlaceholderKey(PlaceHolderKey placeHolderKey) { return results; } + /** + *

Set the player's object, based upon the player's name, or based upon the + * placeholder attribute if a player attribute is provided. + *

+ * + * @param playerUuid + * @param playerName + */ public void setPlayer( UUID playerUuid, String playerName ) { Player player = null; @@ -194,6 +202,28 @@ public void setPlayer( UUID playerUuid, String playerName ) { if ( player != null ) { setPlayer(player); } + else { + // Check placeholder attributes for a defined player's namme: + String pName = getPlayerNameFromPlaceholderAttributes(); + + if ( pName != null ) { + + setPlayer( null, pName ); + } + } + } + + public String getPlayerNameFromPlaceholderAttributes() { + String player = null; + + for (PlaceholderAttribute phAttr : getAttributes() ) { + if ( phAttr.getPlayer() != null ) { + player = phAttr.getPlayer(); + break; + } + } + + return player; } public PlaceholderAttributeBar getAttributeBar() { @@ -235,6 +265,19 @@ public PlaceholderAttributeText getAttributeText() { return phAttribute; } + public PlaceholderAttributeTime getAttributeTime() { + PlaceholderAttributeTime phAttribute = null; + + for (PlaceholderAttribute placeholderAttribute : getAttributes() ) { + if ( placeholderAttribute instanceof PlaceholderAttributeTime ) { + phAttribute = (PlaceholderAttributeTime) placeholderAttribute; + break; + } + } + + return phAttribute; + } + public String getIdentifierRaw() { return identifierRaw; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java index ed75add67..b3cf4bfe7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java @@ -4,6 +4,9 @@ import java.util.List; import java.util.regex.Pattern; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.modules.ModuleManager; + public class PlaceholderManager { public static final String PRISON_PLACEHOLDER_PREFIX = "prison"; @@ -95,7 +98,8 @@ public boolean hasSequence() { public enum PlaceholderAttributePrefixes { nFormat, bar, - text; + text, + time; public static PlaceholderAttributePrefixes fromString( String value ) { PlaceholderAttributePrefixes pap = null; @@ -133,6 +137,27 @@ public static NumberTransformationUnitTypes fromString( String value ) { } } + public enum TimeTransformationUnitTypes { + none, + LONG, + SHORT, + colons; + + public static TimeTransformationUnitTypes fromString( String value ) { + TimeTransformationUnitTypes pap = none; + + if ( value != null ) { + for ( TimeTransformationUnitTypes nTrans : values() ) { + if ( nTrans.name().equalsIgnoreCase( value ) ) { + pap = nTrans; + } + } + } + + return pap; + } + } + /** *

The given place holders should have both the prison prefix and without, * with the without having the suppress value set. The suppressable items @@ -777,11 +802,34 @@ public static List getAllChatList( boolean omitSuppressable) { boolean hasDeprecated = false; + + boolean isMinesEnabled = Prison.get().getModuleManager().isEnabled( ModuleManager.MODULE_NAME_MINES ); + boolean isRanksEnabled = Prison.get().getModuleManager().isEnabled( ModuleManager.MODULE_NAME_RANKS ); + + int totalCount = 0; for ( PlaceholderFlags type : PlaceholderFlags.values() ) { if ( type == PlaceholderFlags.ALIAS || type == PlaceholderFlags.SUPRESS ) { - break; + continue; + } + + if ( !isMinesEnabled && ( + type == PlaceholderFlags.MINES || + type == PlaceholderFlags.MINEPLAYERS || + type == PlaceholderFlags.PLAYERBLOCKS || + type == PlaceholderFlags.STATSMINES )) { + continue; + } + + if ( !isRanksEnabled && ( +// type == PlaceholderFlags.PLAYER && placeholder.name().toLowerCase().contains("rank") || + type == PlaceholderFlags.LADDERS || + type == PlaceholderFlags.RANKS || + type == PlaceholderFlags.RANKPLAYERS || + type == PlaceholderFlags.STATSPLAYERS || + type == PlaceholderFlags.STATSRANKS )) { + continue; } int pos = results.size(); @@ -820,6 +868,11 @@ else if ( type == PlaceholderFlags.STATSRANKS ) { int count = 0; for ( PrisonPlaceHolders ph : values() ) { + if ( !isRanksEnabled && ( + type == PlaceholderFlags.PLAYER && ph.name().toLowerCase().contains("rank") )) { + break; + } + if ( ph.getFlags().contains( type ) && ( !omitSuppressable || omitSuppressable && !ph.isSuppressed() && !ph.isAlias() )) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManagerUtils.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManagerUtils.java index f6c3bff67..6b7ff9aec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManagerUtils.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManagerUtils.java @@ -97,7 +97,8 @@ private PlaceholderAttribute attributeFactory( String rawAttribute ) { if ( rawAttribute != null && !rawAttribute.isEmpty() ) { ArrayList parts = new ArrayList<>(); - parts.addAll( Arrays.asList( rawAttribute.split( PlaceholderManager.PRISON_PLACEHOLDER_ATTRIBUTE_FIELD_SEPARATOR )) ); + parts.addAll( Arrays.asList( + rawAttribute.split( PlaceholderManager.PRISON_PLACEHOLDER_ATTRIBUTE_FIELD_SEPARATOR )) ); if ( parts.size() >= 0 ) { PlaceholderAttributePrefixes pap = PlaceholderAttributePrefixes.fromString( parts.get( 0 ) ); @@ -118,6 +119,12 @@ private PlaceholderAttribute attributeFactory( String rawAttribute ) { attribute = new PlaceholderAttributeText( parts, rawAttribute ); break; + case time: + // Insert the dummy value "format" as the second element of 'parts' since Time does not use it: + parts.add(1, ""); + attribute = new PlaceholderAttributeTime( parts, rawAttribute ); + break; + default: break; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersStats.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersStats.java index bee6b1cf0..56ad91a77 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersStats.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersStats.java @@ -13,7 +13,10 @@ public class PlaceholdersStats { private static PlaceholdersStats stats; - TreeMap placeholders; + private TreeMap placeholders; + + private int invalidWorldCount = 0; + private PlaceholdersStats() { super(); @@ -154,6 +157,13 @@ public ArrayList generatePlaceholderReport() { } + + results.add( + String.format( "&7Invalid World Usage Total: &3%10s &b(Placeholders replaced with banks)", + iFmt.format( getInvalidWorldCount() ) )); + + + return results; } @@ -174,6 +184,7 @@ public void clearCache(boolean resetCache, boolean removeErrors) { getPlaceholders().remove( key ); } + setInvalidWorldCount( 0 ); Output.get().logInfo( "PlaceholderStats: Cache was purged of %s placeholders. Removed: %s ", resetCache ? "all" : @@ -190,5 +201,15 @@ public TreeMap getPlaceholders() { public void setPlaceholders(TreeMap placeholders) { this.placeholders = placeholders; } + + public int incrementInvalidWorldCount() { + return invalidWorldCount++; + } + public int getInvalidWorldCount() { + return invalidWorldCount; + } + public void setInvalidWorldCount(int invalidWorldCount) { + this.invalidWorldCount = invalidWorldCount; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersUtil.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersUtil.java index a1efb18b4..101ebca6e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersUtil.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholdersUtil.java @@ -48,6 +48,31 @@ public class PlaceholdersUtil } } + public static String formattedShortTime( double timeSec, String spaces ) { + + long durationMs = (long) (timeSec * 1000d); + String formattedTime = Text.getTimeUntilShortString( durationMs, spaces ); + + return formattedTime; + } + public static String formattedColonsTime( double timeSec, String spaces ) { + + long durationMs = (long) (timeSec * 1000d); + String formattedTime = Text.getTimeUntilColonsString( durationMs, spaces ); + + String textAnd = " " + Text.coreOutputTextAndMsg() + " "; + + formattedTime = formattedTime.replace( textAnd, "" ); + + return formattedTime; + } + public static String formattedTime( double timeSec, String spaces ) { + + long durationMs = (long) (timeSec * 1000d); + String formattedTime = Text.getTimeUntilString( durationMs, spaces ); + + return formattedTime; + } /** *

Formats seconds to 0d 0h 0m 0s. diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java index 976e61da9..007d2fd87 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java @@ -403,10 +403,15 @@ public int compareTo( Rank r ) } /** - * This new implementation of position is lazy loaded and should never be saved. - * This is to provide a quick reference to the position within the ladder's rank's - * ArrayList. This should never be used to access a rank or to refer to a rank; the + *

This provides a quick reference to the position within the ladder's rank's + * ArrayList. This value is zero based, where the first rank on the ladders has + * a position of 0. + *

+ * + *

This new implementation of position is lazy loaded and should never be saved. + * This should never be used to access a rank or to refer to a rank; the * actual objects should be used for that. + *

* * @return */ diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java index 6021ed64e..06af55f65 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java @@ -114,6 +114,8 @@ public class RankPlayer // private double rankScoreBalanceThreshold = 0; // private long rankScoreCooldown = 0L; + + private long economyCacheUpdateDelayTicks = -1; public RankPlayer() { super(); @@ -1182,6 +1184,19 @@ public double getBalanceUnsaved() { return unsavedBalance; } + + public long getEconomyCacheUpdateDelayTicks() { + + if ( this.economyCacheUpdateDelayTicks == -1 ) { + + this.economyCacheUpdateDelayTicks = + Prison.get().getPlatform().getConfigLong( + "ranks.player-economy-cache-update-delay-ticks", DELAY_THREE_SECONDS ); + } + + return this.economyCacheUpdateDelayTicks; + } + public void addBalance( double amount ) { synchronized ( unsavedBalanceLock ) @@ -1202,7 +1217,7 @@ public void addBalance( double amount ) { unsavedBalance = 0; ubTaskId = 0; } - }, DELAY_THREE_SECONDS ); + }, getEconomyCacheUpdateDelayTicks() ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTasks.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTasks.java index 8706a810d..4a39bdb0f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTasks.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTasks.java @@ -69,12 +69,14 @@ public void run() { else if ( Output.get().isDebug() && cmTasksPosition > 0 ) { // Done running all tasks. If debug is enabled, print: + String playerName = getPlayer() != null ? getPlayer().getName() : null; + String message = String.format( "Prison Command Debug Details: %d", cmTasksPosition ); - Output.get().logDebug( message ); + Output.get().logDebug( message, playerName ); for ( PrisonCommandTaskData cmdTask : cmdTasks ) { - Output.get().logInfo( cmdTask.getDebugDetails() ); + Output.get().logDebug( cmdTask.getDebugDetails(), playerName ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ExampleJavaDoubleVsBigDecimal.java b/prison-core/src/main/java/tech/mcprison/prison/util/ExampleJavaDoubleVsBigDecimal.java index a856abc35..807cd35db 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/ExampleJavaDoubleVsBigDecimal.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ExampleJavaDoubleVsBigDecimal.java @@ -4,8 +4,6 @@ import java.text.DecimalFormat; import java.util.ArrayList; -import tech.mcprison.prison.Prison; - public class ExampleJavaDoubleVsBigDecimal { public static void main( String[] args ) { @@ -15,11 +13,13 @@ public static void main( String[] args ) { ArrayList out = app.runSample(); String header = String.format( - "%s %30s %35s %16s %s", + "%s %45s %3s %55s %3s %35s %s", "Int Digits ", " double ", + "Row", " BigDecimal ", - "Delta ", + "Row", + "Delta - loss of double precision ", "Row" ); System.out.println( header ); @@ -36,9 +36,10 @@ private ArrayList runSample() { StringBuilder sb = new StringBuilder(); sb.append( ".111111" ); - DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.00000" ); + DecimalFormat dFmt = new DecimalFormat( "#,##0.000000" ); +// DecimalFormat iFmt = new DecimalFormat( "#,##0.00000" ); - for ( int i = 1; i < 25; i++ ) { + for ( int i = 1; i < 35; i++ ) { sb.insert( 0, "1" ); double dub = Double.parseDouble( sb.toString() ); @@ -47,12 +48,14 @@ private ArrayList runSample() { BigDecimal delta = bigD.subtract( BigDecimal.valueOf(dub) ); String rpt = String.format( - "%2d %40s %35s %16s %2d", + "%3d %55s %3d %55s %3d %35s %3d", i, dFmt.format( dub ), - bigD.toString(), delta.toString(), - i - ); + i, + dFmt.format( bigD ), + i, + dFmt.format( delta ), + i ); out.add( rpt ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java index 2c2a83a20..734a63a81 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java @@ -38,6 +38,7 @@ public class Location { private Vector direction; private boolean isEdge; + private boolean isCorner; public Location(World world, double x, double y, double z, float pitch, float yaw, Vector direction) { this.world = world; @@ -163,6 +164,13 @@ public void setEdge( boolean isEdge ) { this.isEdge = isEdge; } + public boolean isCorner() { + return isCorner; + } + public void setCorner(boolean isCorner) { + this.isCorner = isCorner; + } + @Override public boolean equals(Object o) { if (this == o) { return true; diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonStatsUtil.java b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonStatsUtil.java index 56857746c..a597c11ae 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonStatsUtil.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonStatsUtil.java @@ -10,14 +10,103 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.TreeSet; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.backups.PrisonBackups; +import tech.mcprison.prison.commands.RegisteredCommand; import tech.mcprison.prison.discord.PrisonPasteChat; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.Output; public class PrisonStatsUtil { + + + /** + *

This will return in a StringBuilder all of the information from the following + * commands. They will be combined in one large StringBuilder object so a table of + * contents can be built from it. This is similar to running the following 4 + * commands, but are better organized with the order of the details (files last). + *

+ * + *
/prison support submit version
+ *
/prison support submit ranks
+ *
/prison support submit mines
+ *
/prison support submit commands
+ * + *

The difference with this function, is that all of the raw files are + * included at the end, instead of being mixed in with the other non-raw file + * dumps. + *

+ * + *

Order of reports:

+ *
    + *
  • Version ALL
  • + *
  • listeners ALL
  • + *
  • Command Stats
  • + * + *
  • Ladder List - Missing?
  • + *
  • Rank List
  • + *
  • Rank details
  • + * + *
  • Mine List
  • + *
  • Mine details
  • + * + *
  • Prison Backup Files
  • + + *
  • Ladder Files
  • + *
  • Rank Files
  • + * + *
  • Mine Files
  • + * + *
  • ConfigSettings Files
  • + * + *
+ * + * @return + */ + public StringBuilder getSupportSubmitBasic() { + StringBuilder sb = new StringBuilder(); + + // version info: + sb.append( getSupportSubmitVersionData() ); + + // Listeners: + sb.append( getSupportSubmitListenersData( "all" ) ); + + // Command Stats: + sb.append( getCommandStatsDetailData() ); + + + // Rank Lists and Rank details: + sb.append( getSupportSubmitRanksData() ); + + + // Mine lists and Mine details: + sb.append( getSupportSubmitMinesData() ); + + + // Backup log files: + sb.append( getPrisonBackupLogsData() ); + + + // Rank Files: + sb.append( getSupportSubmitRanksFileData() ); + + + // Mine files: + sb.append( getSupportSubmitMinesFileData() ); + + + // Config files: + sb.append( getSupportSubmitConfigsData() ); + + + sb.append( getColorTest() ); + + return sb; + } public ChatDisplay displayVersion(String options) { @@ -52,6 +141,61 @@ public StringBuilder getSupportSubmitVersionData() { return text; } + + public StringBuilder getColorTest() { + StringBuilder sb = new StringBuilder(); + + sb.append( "\n\n" ); + sb.append( "Color Test:\n\n" ); + sb.append( "||Color Test||\n" ); + + sb.append( "&0######### &r&1######### &r&2#########\n" ); + sb.append( "&0### 0 ### &r&1### 1 ### &r&2### 2 ###\n" ); + sb.append( "&0######### &r&1######### &r&2#########\n" ); + + sb.append( "&3######### &r&4######### &r&5#########\n" ); + sb.append( "&3### 3 ### &r&4### 4 ### &r&5### 5 ###\n" ); + sb.append( "&3######### &r&4######### &r&5#########\n" ); + + sb.append( "&6######### &r&7######### &r&8#########\n" ); + sb.append( "&6### 6 ### &r&7### 7 ### &r&8### 8 ###\n" ); + sb.append( "&6######### &r&7######### &r&8#########\n" ); + + sb.append( "&9######### &r&a######### &r&b#########\n" ); + sb.append( "&9### 9 ### &r&a### a ### &r&b### b ###\n" ); + sb.append( "&9######### &r&a######### &r&b#########\n" ); + + sb.append( "&c######### &r&d######### &r&e#########\n" ); + sb.append( "&c### c ### &r&d### d ### &r&e### e ###\n" ); + sb.append( "&c######### &r&d######### &r&e#########\n" ); + + sb.append( "&f######### &r\n" ); + sb.append( "&f### f ### &r\n" ); + sb.append( "&f######### &r\n" ); + + + sb.append( "&3&l#####################&r\n" ); + sb.append( "&3&l### Bold & 3 ###&r\n" ); + sb.append( "&3&l#####################&r\n" ); + + sb.append( "&3&m#####################&r\n" ); + sb.append( "&3&m### Strike & 3 ###&r\n" ); + sb.append( "&3&m#####################&r\n" ); + + sb.append( "&3&n#####################&r\n" ); + sb.append( "&3&n### Underline & 3 ###&r\n" ); + sb.append( "&3&n#####################&r\n" ); + + sb.append( "&3&o#####################&r\n" ); + sb.append( "&3&o### Italic & 3 ###&r\n" ); + sb.append( "&3&o#####################&r\n" ); + + sb.append( "\n\n" ); + + return sb; + } + + public StringBuilder getSupportSubmitConfigsData() { Prison.get().getPlatform().saveResource("plugin.yml", true); @@ -102,14 +246,30 @@ public void copyConfigsFiles() { } - + public StringBuilder getSupportSubmitRanksData() { + + StringBuilder text = new StringBuilder(); + + text.append(Prison.get().getPlatform().getRanksListString()); + printFooter(text); + +// List files = listFiles("data_storage/ranksDb/ladders/", ".json"); +// files.addAll(listFiles("data_storage/ranksDb/ranks/", ".json")); +// for (File file : files) { +// +// addFileToText(file, text); +// } + + return text; + } + + public StringBuilder getSupportSubmitRanksFileData() { List files = listFiles("data_storage/ranksDb/ladders/", ".json"); files.addAll(listFiles("data_storage/ranksDb/ranks/", ".json")); StringBuilder text = new StringBuilder(); - text.append(Prison.get().getPlatform().getRanksListString()); printFooter(text); for (File file : files) { @@ -121,28 +281,46 @@ public StringBuilder getSupportSubmitRanksData() { } public StringBuilder getSupportSubmitMinesData() { - List files = listFiles("data_storage/mines/mines/", ".json"); - Collections.sort(files); +// List files = listFiles("data_storage/mines/mines/", ".json"); +// Collections.sort(files); StringBuilder text = new StringBuilder(); - text.append("\n"); - text.append("Table of contents:\n"); - text.append(" 1. Mine list - All mines including virtual mines: /mines list all\n"); - text.append(" 2. Mine info - All mines: /mines info all\n"); - text.append(" 3. Mine files - Raw JSON dump of all mine configuration files.\n"); - text.append("\n"); +// text.append("\n"); +// text.append("Table of contents:\n"); +// text.append(" 1. Mine list - All mines including virtual mines: /mines list all\n"); +// text.append(" 2. Mine info - All mines: /mines info all\n"); +// text.append(" 3. Mine files - Raw JSON dump of all mine configuration files.\n"); +// text.append("\n"); // Display a list of all mines, then display the /mines info all for // each: text.append(Prison.get().getPlatform().getMinesListString()); - printFooter(text); +// printFooter(text); +// // get all the file details for each mine: +// for (File file : files) { +// +// addFileToText(file, text); +// } + + return text; + } + + public StringBuilder getSupportSubmitMinesFileData() { + List files = listFiles("data_storage/mines/mines/", ".json"); + Collections.sort(files); + + StringBuilder text = new StringBuilder(); + + printFooter(text); + + // get all the file details for each mine: for (File file : files) { - + addFileToText(file, text); - } + return text; } @@ -156,11 +334,13 @@ public StringBuilder getSupportSubmitListenersData( String listenerType ) { if ( "blockBreak".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + sb.append( "||Listeners blockBreak||" ); sb.append( Prison.get().getPlatform().dumpEventListenersBlockBreakEvents() ); } if ( "chat".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + sb.append( "||Listeners chat||" ); sb.append( Prison.get().getPlatform().dumpEventListenersPlayerChatEvents() ); } @@ -172,12 +352,109 @@ public StringBuilder getSupportSubmitListenersData( String listenerType ) { if ( "playerInteract".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + sb.append( "||Listeners playerInteract||" ); sb.append( Prison.get().getPlatform().dumpEventListenersPlayerInteractEvents() ); } return sb; } + + public StringBuilder getCommandStatsDetailData() { + StringBuilder sb = new StringBuilder(); + + sb.append( "\n\n" ); + + List cmds = getCommandStats(); + cmds.add( 1, "||CommandStats List||" ); + + for (String cmd : cmds) { + + sb.append( cmd ).append( "\n" ); + } + + return sb; + } + + public void getCommandStatsData() { + + List cmds = getCommandStats(); + for (String cmd : cmds) { + + Output.get().logInfo( cmd ); + } + } + + private List getCommandStats() { + List results = new ArrayList<>(); + + DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); + DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); + + TreeSet allCmds = Prison.get().getCommandHandler().getAllRegisteredCommands(); + + results.add( "Prison Command Stats:" ); + results.add( + Output.stringFormat( " &a&n%-40s&r &a&n%7s&r &a&n%-11s&r", + " Commands ", " Usage ", " Avg ms ") ); + + int count = 0; + int totals = 0; + double totalDuration = 0d; + for (RegisteredCommand cmd : allCmds) { + + if ( cmd.getUsageCount() > 0 ) { + + double duration = cmd.getUsageRunTimeNanos() / (double) cmd.getUsageCount() / 1000000.0d; + + results.add( Output.stringFormat( " &2%-40s &2%7s &2%11s", + cmd.getCompleteLabel(), + iFmt.format( cmd.getUsageCount() ), + dFmt.format( duration ) + ) ); + count++; + totals += cmd.getUsageCount(); + totalDuration += cmd.getUsageRunTimeNanos(); + } + } + + results.add( Output.stringFormat(" &3Total Registered Prison Commands: &7%9s", iFmt.format( allCmds.size() )) ); + results.add( Output.stringFormat(" &3Total Prison Commands Listed: &7%9s", iFmt.format( count )) ); + results.add( Output.stringFormat(" &3Total Prison Command Usage: &7%9s", iFmt.format( totals )) ); + + double avgDuration = totalDuration / (double) count / 1000000.0d; + results.add( Output.stringFormat(" &3Average Command Duration ms: &7%9s", dFmt.format( avgDuration )) ); + + results.add( " &d&oNOTE: Async Commands like '/mines reset' will not show actual runtime values. " ); + + + return results; + } + + + public StringBuilder getPrisonBackupLogsData() { + StringBuilder sb = new StringBuilder(); + + // Include Prison backup logs: + sb.append( "\n\n" ); + sb.append( "Prison Backup Logs:" ).append( "\n" ); + List backupLogs = getPrisonBackupLogs(); + + for (String log : backupLogs) { + sb.append( Output.decodePercentEncoding(log) ).append( "\n" ); + } + + return sb; + } + + + public List getPrisonBackupLogs() { + PrisonBackups prisonBackup = new PrisonBackups(); + List backupLogs = prisonBackup.backupReport02BackupLog(); + return backupLogs; + } + + public void readFileToStringBulider(File textFile, StringBuilder text) { try (BufferedReader br = Files.newBufferedReader(textFile.toPath());) { String line = br.readLine(); @@ -220,20 +497,71 @@ private List listFiles(String path, String fileSuffix) { } private void addFileToText(File file, StringBuilder sb) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); + DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); SimpleDateFormat sdFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + String parentDirName = file.getParentFile().getName(); + + String header = ""; + String name = ""; + + if ( "ranks".equalsIgnoreCase(parentDirName) ) { + // Rank file names have a prefix of "ranks_" and then the rankId, followed by the suffix. + // Need to use the rankId to find the rank's name: + + header = "Rank"; + name = Prison.get().getPlatform().getRankByFileName( file.getName() ); + } + else if ( "ladders".equalsIgnoreCase(parentDirName) ) { + // Ladder file names have a prefix of "ladders_" and then the ladderId, followed by the suffix. + // Need to use the ladderId to find the ladder's name: + + header = "Ladder"; + name = Prison.get().getPlatform().getLadderByFileName( file.getName() ); + } + else if ( "mines".equalsIgnoreCase(parentDirName) ) { + // The file name of the mine, minus the suffix, is the name's name. + + header = "Mine"; + name = file.getName().replace(".json", ""); + } + else { + header = "Config"; + name = file.getName(); + } + + sb.append("\n"); JumboTextFont.makeJumboFontText(file.getName(), sb); sb.append("\n"); + - sb.append("File Name: ").append(file.getName()).append("\n"); - sb.append("File Path: ").append(file.getAbsolutePath()).append("\n"); - sb.append("File Size: ").append(dFmt.format(file.length())).append(" bytes\n"); - sb.append("File Date: ").append(sdFmt.format(new Date(file.lastModified()))).append(" bytes\n"); - sb.append("File Stats: ").append(file.exists() ? "EXISTS " : "").append(file.canRead() ? "READABLE " : "") + // Hyper Link codes: + sb.append( "||" ) + .append( header ) + .append( " " ) + .append( name ) + .append( " " ) + .append( "File" ) + .append( "||\n" ); + + String prisonPath = Prison.get().getDataFolder().getAbsolutePath(); + String filePath = file.getAbsolutePath().replace( prisonPath, "" ); + + long fileSize = file.length(); + double fileSizeKB = fileSize / 1024.0; + + sb.append("File Name: ").append( file.getName() ).append("\n"); + sb.append("Prison Path: ").append( prisonPath ).append("\n"); + sb.append("File Path: ").append( filePath ).append("\n"); + sb.append("File Size: ").append( iFmt.format( fileSize ) ).append(" bytes\n"); + sb.append("File Size: ").append( dFmt.format( fileSizeKB ) ).append(" KB\n"); + sb.append("File Date: ").append( sdFmt.format(new Date(file.lastModified())) ).append(" \n"); + sb.append("File Stats: ").append( file.exists() ? "EXISTS " : "" ).append(file.canRead() ? "READABLE " : "") .append(file.canWrite() ? "WRITEABLE " : "").append("\n"); sb.append("\n"); @@ -241,7 +569,9 @@ private void addFileToText(File file, StringBuilder sb) { sb.append("\n"); if (file.exists() && file.canRead()) { + sb.append("&-"); readFileToStringBulider(file, sb); + sb.append("\n&+"); } else { sb.append("Warning: The file is not readable so it cannot be included.\n"); } @@ -251,7 +581,7 @@ private void addFileToText(File file, StringBuilder sb) { public void printFooter(StringBuilder sb) { - sb.append("\n\n\n"); + sb.append("\n\n"); sb.append("=== --- === --- === --- === --- === --- ===\n"); sb.append("=== # # ### # # # ### # # # ### # # # ### # # # ### # # ===\n"); sb.append("=== --- === --- === --- === --- === --- ===\n"); 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 01088b199..c9af8c48f 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 @@ -63,6 +63,26 @@ public class Text "minute:minutes", millisPerMinute, "second:seconds", millisPerSecond); + private static Map unitMillisShort = CollectionUtil + .map( + "y", millisPerYear, + "m", millisPerMonth, + "w", millisPerWeek, + "d", millisPerDay, + "h", millisPerHour, + "m", millisPerMinute, + "s", millisPerSecond); + + private static Map unitMillisColons = CollectionUtil + .map( + "y", millisPerYear, + "m", millisPerMonth, + "w", millisPerWeek, + "day:", millisPerDay, + "hour:", millisPerHour, + "min:", millisPerMinute, + "", millisPerSecond); + private static String unit_time_text_prefix = "&3"; private static String unit_time_text_just_now = "just now"; private static String unit_time_text_ago = "ago"; @@ -115,6 +135,9 @@ public static void initialize() { String timeUnitsSingular = coreOutputTextTimeUnitsSingularMsg(); String timeUnitsPlural = coreOutputTextTimeUnitsPluralMsg(); + + String timeUnitsShort = coreOutputTextTimeUnitsShortMsg(); + String[] tuS = timeUnitsSingular.split( "," ); String[] tuP = timeUnitsPlural.split( "," ); @@ -131,6 +154,40 @@ public static void initialize() { unitMillis.put( tuS[i] + ":" + tuP[i++], millisPerMinute ); unitMillis.put( tuS[i] + ":" + tuP[i++], millisPerSecond ); } + + + String[] tuShort = timeUnitsShort.split( "," ); + + if ( tuShort.length == 7 ) { + unitMillisShort = new LinkedHashMap<>(); + + int i = 0; + unitMillisShort.put( tuShort[i++], millisPerYear ); + unitMillisShort.put( tuShort[i++], millisPerMonth ); + unitMillisShort.put( tuShort[i++], millisPerWeek ); + unitMillisShort.put( tuShort[i++], millisPerDay ); + unitMillisShort.put( tuShort[i++], millisPerHour ); + unitMillisShort.put( tuShort[i++], millisPerMinute ); + unitMillisShort.put( tuShort[i++], millisPerSecond ); + + } + + if ( tuShort.length == 7 ) { + unitMillisColons = new LinkedHashMap<>(); + + int i = 0; + unitMillisColons.put( tuShort[i++], millisPerYear ); + unitMillisColons.put( tuShort[i++], millisPerMonth ); + unitMillisColons.put( tuShort[i++], millisPerWeek ); + unitMillisColons.put( "day:", millisPerDay ); + unitMillisColons.put( "hour:", millisPerHour ); + unitMillisColons.put( "min:", millisPerMinute ); + unitMillisColons.put( "", millisPerSecond ); + + } + + + } /** @@ -572,18 +629,33 @@ public static String tab(String text) { * @return The human-readable string. */ public static String getTimeUntilString(long millis) { + return getTimeUntilString( millis, unitMillis, unitPrefixSpacer, null ); + } + public static String getTimeUntilString(long millis, String spaces ) { + return getTimeUntilString( millis, unitMillis, spaces, null ); + } + public static String getTimeUntilShortString(long millis, String spaces ) { + return getTimeUntilString( millis, unitMillisShort, spaces, null ); + } + public static String getTimeUntilColonsString(long millis, String spaces ) { + DecimalFormat dFmt = new DecimalFormat( "00" ); + return getTimeUntilString( millis, unitMillisColons, spaces, dFmt ); + } + private static String getTimeUntilString(long millis, Map units, + String unitSpacer, DecimalFormat dFmt ) { String ret = unit_time_text_prefix; double millisLeft = (double) Math.abs(millis); List unitCountParts = new ArrayList<>(); - for (Map.Entry entry : unitMillis.entrySet()) { + for (Map.Entry entry : units.entrySet()) { if (unitCountParts.size() == 3) { break; } + boolean isColons = ( entry.getKey().endsWith( ":" ) ); String[] unitNames = entry.getKey().split( ":" ); - String unitNameSingular = unitNames[0]; - String unitNamePlural = unitNames.length > 1 ? unitNames[1] : unitNames[0]; + String unitNameSingular = isColons ? ":" : unitNames[0]; + String unitNamePlural = isColons ? ":" : unitNames.length > 1 ? unitNames[1] : unitNames[0]; long unitSize = entry.getValue(); long unitCount = (long) Math.floor(millisLeft / unitSize); @@ -592,7 +664,9 @@ public static String getTimeUntilString(long millis) { } millisLeft -= unitSize * unitCount; - unitCountParts.add(unitCount + unitPrefixSpacer + + String unitCountStr = dFmt == null ? Long.toString( unitCount ) : dFmt.format( unitCount ); + + unitCountParts.add( unitCountStr + unitSpacer + ( unitCount == 1 ? unitNameSingular : unitNamePlural) ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/TextMessage.java b/prison-core/src/main/java/tech/mcprison/prison/util/TextMessage.java index 7d3ebf2ce..7d5c3b9c8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/TextMessage.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/TextMessage.java @@ -46,7 +46,7 @@ protected static String coreOutputTextFromNowMsg() { .localize(); } - protected static String coreOutputTextAndMsg() { + public static String coreOutputTextAndMsg() { return Prison.get().getLocaleManager() .getLocalizable( "core_text__and" ) .withReplacements( "%s" ) @@ -77,5 +77,13 @@ protected static String coreOutputTextTimeUnitsPluralMsg() { .setFailSilently() .localize(); } + + protected static String coreOutputTextTimeUnitsShortMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_text__time_units_short" ) + .withReplacements( "%s" ) + .setFailSilently() + .localize(); + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldEdit.java b/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldEdit.java new file mode 100644 index 000000000..390cb4fa0 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldEdit.java @@ -0,0 +1,5 @@ +package tech.mcprison.prison.worldguard; + +public abstract class PrisonWorldEdit { + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldGuard.java b/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldGuard.java new file mode 100644 index 000000000..8757b7419 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/worldguard/PrisonWorldGuard.java @@ -0,0 +1,5 @@ +package tech.mcprison.prison.worldguard; + +public abstract class PrisonWorldGuard { + +} diff --git a/prison-core/src/main/resources/lang/core/de_DE.properties b/prison-core/src/main/resources/lang/core/de_DE.properties index deb59d124..e426fcec9 100644 --- a/prison-core/src/main/resources/lang/core/de_DE.properties +++ b/prison-core/src/main/resources/lang/core/de_DE.properties @@ -64,6 +64,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -84,7 +93,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/en_GB.properties b/prison-core/src/main/resources/lang/core/en_GB.properties index f9b079bd7..12a920078 100644 --- a/prison-core/src/main/resources/lang/core/en_GB.properties +++ b/prison-core/src/main/resources/lang/core/en_GB.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/en_US.properties b/prison-core/src/main/resources/lang/core/en_US.properties index 9533f6cea..c5499c0d2 100644 --- a/prison-core/src/main/resources/lang/core/en_US.properties +++ b/prison-core/src/main/resources/lang/core/en_US.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/es_ES.properties b/prison-core/src/main/resources/lang/core/es_ES.properties index 590e00ba6..b6e6fbcde 100644 --- a/prison-core/src/main/resources/lang/core/es_ES.properties +++ b/prison-core/src/main/resources/lang/core/es_ES.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/fi_FI.properties b/prison-core/src/main/resources/lang/core/fi_FI.properties index 424e2488a..831d6af77 100644 --- a/prison-core/src/main/resources/lang/core/fi_FI.properties +++ b/prison-core/src/main/resources/lang/core/fi_FI.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/fr_FR.properties b/prison-core/src/main/resources/lang/core/fr_FR.properties index d33f66512..9997d0444 100644 --- a/prison-core/src/main/resources/lang/core/fr_FR.properties +++ b/prison-core/src/main/resources/lang/core/fr_FR.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Envoi à System.err en raison de l'échec du log d'Output.log): core_output__error_incorrect_number_of_parameters=Échec du log (%1): Nombre de paramètres incorrect: [%2] Message brut original: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/hu_HU.properties b/prison-core/src/main/resources/lang/core/hu_HU.properties index 6dcfc75bc..fee17ae76 100644 --- a/prison-core/src/main/resources/lang/core/hu_HU.properties +++ b/prison-core/src/main/resources/lang/core/hu_HU.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/it_IT.properties b/prison-core/src/main/resources/lang/core/it_IT.properties index 3da4b9a97..7868eee2f 100644 --- a/prison-core/src/main/resources/lang/core/it_IT.properties +++ b/prison-core/src/main/resources/lang/core/it_IT.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/nl_BE.properties b/prison-core/src/main/resources/lang/core/nl_BE.properties index 6e970e303..bec93ed55 100644 --- a/prison-core/src/main/resources/lang/core/nl_BE.properties +++ b/prison-core/src/main/resources/lang/core/nl_BE.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/nl_NL.properties b/prison-core/src/main/resources/lang/core/nl_NL.properties index f8be4ce03..270b1fc24 100644 --- a/prison-core/src/main/resources/lang/core/nl_NL.properties +++ b/prison-core/src/main/resources/lang/core/nl_NL.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/pt_PT.properties b/prison-core/src/main/resources/lang/core/pt_PT.properties index 0a3281bf5..9c87f5f9d 100644 --- a/prison-core/src/main/resources/lang/core/pt_PT.properties +++ b/prison-core/src/main/resources/lang/core/pt_PT.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/ro_RO.properties b/prison-core/src/main/resources/lang/core/ro_RO.properties index ed5bf728a..647284ad2 100644 --- a/prison-core/src/main/resources/lang/core/ro_RO.properties +++ b/prison-core/src/main/resources/lang/core/ro_RO.properties @@ -59,6 +59,15 @@ # nefiind È™ters, poÈ›i integra manual schimbările în fiÈ™ierul nou. FiÈ™ierele vechi, redenumite # nu vor fi È™terse de către Prison; poÈ›i să le È™tergi când consideri că este sigur să o faci. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # PuteÈ›i ajuta Prison È™i utilizatorii acestuia prin a adăuga traduceri în alte limbi. # Acestea ar trebui să fie traduceri precise, ce menÈ›in înÈ›elesul mesajului original, # fără glume de prost gust È™i abateri de la semnificaÈ›ia originală. Dacă doreÈ™ti să @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/zh-CN.properties b/prison-core/src/main/resources/lang/core/zh-CN.properties index 3d48d2fc8..cfeca845d 100644 --- a/prison-core/src/main/resources/lang/core/zh-CN.properties +++ b/prison-core/src/main/resources/lang/core/zh-CN.properties @@ -62,6 +62,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -82,7 +91,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=监狱: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters= 日志失败(%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/core/zh_TW.properties b/prison-core/src/main/resources/lang/core/zh_TW.properties index 7cc23d779..99880acb3 100644 --- a/prison-core/src/main/resources/lang/core/zh_TW.properties +++ b/prison-core/src/main/resources/lang/core/zh_TW.properties @@ -61,6 +61,15 @@ # renamed files will never be deleted by prison; you can remove them when you feel like it # is safe to do so. # +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# # Please consider helping Prison, and everyone else who may use Prison, by contributing all # translations to other languages. They should be faithful translations, and not something # for the sake of humor or changes just for cosmetic styling. If you have something you would @@ -81,7 +90,7 @@ core_output__prefix_template_debug=Debug core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c -core_output__color_code_debug=&9 +core_output__color_code_debug=&b core_output__error_startup_failure=Prison: (Sending to System.err due to Output.log Logger failure): core_output__error_incorrect_number_of_parameters=Log Failure (%1): Incorrect number of parameters: [%2] Original raw message: [%3] Arguments: %4 diff --git a/prison-core/src/main/resources/lang/mines/de_DE.properties b/prison-core/src/main/resources/lang/mines/de_DE.properties index b8c0f73f4..da99ff80f 100644 --- a/prison-core/src/main/resources/lang/mines/de_DE.properties +++ b/prison-core/src/main/resources/lang/mines/de_DE.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/en_US.properties b/prison-core/src/main/resources/lang/mines/en_US.properties index 3f86d76e8..d7c409967 100644 --- a/prison-core/src/main/resources/lang/mines/en_US.properties +++ b/prison-core/src/main/resources/lang/mines/en_US.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/es_ES.properties b/prison-core/src/main/resources/lang/mines/es_ES.properties index c6bbeb44f..11692e63a 100644 --- a/prison-core/src/main/resources/lang/mines/es_ES.properties +++ b/prison-core/src/main/resources/lang/mines/es_ES.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/fi_FI.properties b/prison-core/src/main/resources/lang/mines/fi_FI.properties index 0600f57f3..4d8607849 100644 --- a/prison-core/src/main/resources/lang/mines/fi_FI.properties +++ b/prison-core/src/main/resources/lang/mines/fi_FI.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/fr_FR.properties b/prison-core/src/main/resources/lang/mines/fr_FR.properties index 4928b82e5..d6cf696c7 100644 --- a/prison-core/src/main/resources/lang/mines/fr_FR.properties +++ b/prison-core/src/main/resources/lang/mines/fr_FR.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/hu_HU.properties b/prison-core/src/main/resources/lang/mines/hu_HU.properties index 8748e42d6..e1d896577 100644 --- a/prison-core/src/main/resources/lang/mines/hu_HU.properties +++ b/prison-core/src/main/resources/lang/mines/hu_HU.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/it_IT.properties b/prison-core/src/main/resources/lang/mines/it_IT.properties index ee9efefba..e3e9aea98 100644 --- a/prison-core/src/main/resources/lang/mines/it_IT.properties +++ b/prison-core/src/main/resources/lang/mines/it_IT.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/nl_BE.properties b/prison-core/src/main/resources/lang/mines/nl_BE.properties index 921617ad9..e56e952e1 100644 --- a/prison-core/src/main/resources/lang/mines/nl_BE.properties +++ b/prison-core/src/main/resources/lang/mines/nl_BE.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/nl_NL.properties b/prison-core/src/main/resources/lang/mines/nl_NL.properties index 1013398f9..3ae2e01cb 100644 --- a/prison-core/src/main/resources/lang/mines/nl_NL.properties +++ b/prison-core/src/main/resources/lang/mines/nl_NL.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/pt_PT.properties b/prison-core/src/main/resources/lang/mines/pt_PT.properties index b1dd86d80..ede5b9ef7 100644 --- a/prison-core/src/main/resources/lang/mines/pt_PT.properties +++ b/prison-core/src/main/resources/lang/mines/pt_PT.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/ro_RO.properties b/prison-core/src/main/resources/lang/mines/ro_RO.properties index c875ef329..97432e42f 100644 --- a/prison-core/src/main/resources/lang/mines/ro_RO.properties +++ b/prison-core/src/main/resources/lang/mines/ro_RO.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=4 diff --git a/prison-core/src/main/resources/lang/mines/zh-CN.properties b/prison-core/src/main/resources/lang/mines/zh-CN.properties index b30302b63..29973987e 100644 --- a/prison-core/src/main/resources/lang/mines/zh-CN.properties +++ b/prison-core/src/main/resources/lang/mines/zh-CN.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=3 diff --git a/prison-core/src/main/resources/lang/mines/zh_TW.properties b/prison-core/src/main/resources/lang/mines/zh_TW.properties index ea87cda68..1ad538fbb 100644 --- a/prison-core/src/main/resources/lang/mines/zh_TW.properties +++ b/prison-core/src/main/resources/lang/mines/zh_TW.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=5 diff --git a/prison-core/src/main/resources/lang/ranks/en_US.properties b/prison-core/src/main/resources/lang/ranks/en_US.properties index ff6e18da4..8d0fc484d 100644 --- a/prison-core/src/main/resources/lang/ranks/en_US.properties +++ b/prison-core/src/main/resources/lang/ranks/en_US.properties @@ -49,8 +49,19 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# +# NOTE: You can add line feeds to your messages by inserting the placeholder '{br}'. +# -messages__version=28 +messages__version=29 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=You have @@ -250,7 +261,7 @@ ranks_rankCommands__error_writting_ladder=&3The '&7%1&3' ladder could not be sav ranks_rankCommands__auto_config_preexisting_warning=&3You are trying to run &7/ranks autoConfigure&3 with ranks or mines already setup. Rank count = &7%1&3. Mine count = &7%2&3. Please run this command with the &7help&3 keyword for more information and other customization options: &7/ranks autoConfigure help&3. It's best to run this command from the &7console&3 due to the volume of data it generates. Add the option '&7force&3' to force this process to run. If there is a conflict with a preexisting rank or mine, this process will do it's best to merge the new ranks and mines with what already exist. There is the risk something may not merge correctly. When merging, all blocks will be replaced, but in the console the original block list will be printed for reference if you want to recreate them. Please backup your &7plugins/Prison/&3 directory before running to be safe. ranks_rankCommands__auto_config_force_warning=&aWarning! &3Running autoConfigure with &7force&3 enabled. Not responsible if mines or ranks collide. -ranks_rankCommands__auto_config_invalid_options=&3Invalid options. Use %1&3. Was: &3%2 +ranks_rankCommands__auto_config_invalid_options=&3Invalid options detected. {br}Use %1&3. {br}&3The unknown remaining options were: [&7%2&3] ranks_rankCommands__auto_config_skip_rank_warning=&aWarning! &3Rank &7%1 &3already exists and is being skipped along with generating the mine if enabled, along with all of the other features. ranks_rankCommands__auto_config_no_ranks_created=Ranks autoConfigure: No ranks were created. diff --git a/prison-core/src/main/resources/lang/ranks/fr_FR.properties b/prison-core/src/main/resources/lang/ranks/fr_FR.properties index 90af5af69..6f5e7f54e 100644 --- a/prison-core/src/main/resources/lang/ranks/fr_FR.properties +++ b/prison-core/src/main/resources/lang/ranks/fr_FR.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=28 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/ranks/pt_PT.properties b/prison-core/src/main/resources/lang/ranks/pt_PT.properties index 9210d41b4..c6f5ada05 100644 --- a/prison-core/src/main/resources/lang/ranks/pt_PT.properties +++ b/prison-core/src/main/resources/lang/ranks/pt_PT.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=6 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/ranks/zh-CN.properties b/prison-core/src/main/resources/lang/ranks/zh-CN.properties index 0bdc603b6..9111dfdcb 100644 --- a/prison-core/src/main/resources/lang/ranks/zh-CN.properties +++ b/prison-core/src/main/resources/lang/ranks/zh-CN.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=25 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/ranks/zh_TW.properties b/prison-core/src/main/resources/lang/ranks/zh_TW.properties index a503b64b9..88443d906 100644 --- a/prison-core/src/main/resources/lang/ranks/zh_TW.properties +++ b/prison-core/src/main/resources/lang/ranks/zh_TW.properties @@ -49,6 +49,15 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# messages__version=9 messages__auto_refresh=true @@ -130,7 +139,7 @@ ranks_prisonRanks__failure_loading_players=玩家資料資料失敗. %1 ranks_prisonRanks__failed_loading_players=&c無法載入玩家: %1 ranks_prisonRanks__failed_to_load_player_file=玩家資料載入失敗. %1 -ranks_prisonRanks__status_loaded_ranks=載入 %1 éšŽç´ default ranks: %2 prestige ranks: %3 other ranks: %4 +ranks_prisonRanks__status_loaded_ranks=載入 %1 階� default ranks: %2 prestige ranks: %3 other ranks: %4 ranks_prisonRanks__status_loaded_ladders=載入 %1 階 ranks_prisonRanks__status_loaded_players=載入 %1 玩家 @@ -272,8 +281,8 @@ ranks_rankCommands__rank_was_removed=階級 '%1' 已刪除æˆåŠŸ ranks_rankCommands__rank_delete_error=階級 '%1' 因出ç¾éŒ¯èª¤è€Œåˆªé™¤å¤±æ•— -ranks_rankCommands__ranks_list_header=%1 中的 éšŽç´ -šranks_rankCommands__ranks_list_ladder_cost_multplier=&3 Ladder Rank Cost Multiplier per Rank: &7%1 +ranks_rankCommands__ranks_list_header=%1 中的 階� +�ranks_rankCommands__ranks_list_ladder_cost_multplier=&3 Ladder Rank Cost Multiplier per Rank: &7%1 ranks_rankCommands__ranks_list_ladder_apply_ranks_cost_multplier=&3 Apply global Rank Cost Multipliers to this Rank? &7%1 ranks_rankCommands__ranks_list_ladder_edit_cost_multplier=Edit this Ladder's Rank Cost Multiplier. diff --git a/prison-core/src/main/resources/lang/sellall/en_US.properties b/prison-core/src/main/resources/lang/sellall/en_US.properties index 916f8cfb4..b83231b04 100644 --- a/prison-core/src/main/resources/lang/sellall/en_US.properties +++ b/prison-core/src/main/resources/lang/sellall/en_US.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/sellall/fi_FI.properties b/prison-core/src/main/resources/lang/sellall/fi_FI.properties index bc3352c73..62ecd191f 100644 --- a/prison-core/src/main/resources/lang/sellall/fi_FI.properties +++ b/prison-core/src/main/resources/lang/sellall/fi_FI.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true @@ -58,10 +68,10 @@ sellall_function__message=&dNormaali viesti sellall_spigot_utils__money_earned=&3Tienasit &a$%1 -sellall_spigot_utils__only_sellall_signs_are_enabled=&3Voit vain myydä kylteillä, komento disabloitu. +sellall_spigot_utils__only_sellall_signs_are_enabled=&3Voit vain myyd� kylteill�, komento disabloitu. sellall_spigot_utils__rate_limit_exceeded=&3Hidasta.. -sellall_spigot_utils__shop_is_empty=&3Anteeksi, tämä myynti kauppa on tyhjä.. -sellall_spigot_utils__you_have_nothing_to_sell=&3Anteeksi, sinulla ei ole myytävää. +sellall_spigot_utils__shop_is_empty=&3Anteeksi, t�m� myynti kauppa on tyhj�.. +sellall_spigot_utils__you_have_nothing_to_sell=&3Anteeksi, sinulla ei ole myyt�v��. sellall_spigot_utils__sellall_is_disabled=&3Anteeksi, sellall on disabloitu sellall_spigot_utils__sellall_gui_is_disabled=&3Sorry, the sellall GUI is disabled.. diff --git a/prison-core/src/main/resources/lang/sellall/fr_FR.properties b/prison-core/src/main/resources/lang/sellall/fr_FR.properties index 10d609a7a..2ae8bca16 100644 --- a/prison-core/src/main/resources/lang/sellall/fr_FR.properties +++ b/prison-core/src/main/resources/lang/sellall/fr_FR.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/sellall/pt_PT.properties b/prison-core/src/main/resources/lang/sellall/pt_PT.properties index 5fa3d2a7e..1cc23b939 100644 --- a/prison-core/src/main/resources/lang/sellall/pt_PT.properties +++ b/prison-core/src/main/resources/lang/sellall/pt_PT.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/sellall/zh_CN.properties b/prison-core/src/main/resources/lang/sellall/zh_CN.properties index eb9e536b4..589235f44 100644 --- a/prison-core/src/main/resources/lang/sellall/zh_CN.properties +++ b/prison-core/src/main/resources/lang/sellall/zh_CN.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/spigot/en_US.properties b/prison-core/src/main/resources/lang/spigot/en_US.properties index a53f646b3..7207e9d4f 100644 --- a/prison-core/src/main/resources/lang/spigot/en_US.properties +++ b/prison-core/src/main/resources/lang/spigot/en_US.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=6 messages__auto_refresh=true @@ -215,20 +225,20 @@ spigot_message_prestiges_cancelled_wrong_keyword=Prestige &ccancelled&7, you did ## Ranks Messages spigot_message_ranks_disabled=Sorry, Ranks are disabled. spigot_message_ranks_or_gui_disabled=Sorry, Ranks or GUIs are disabled. -spigot_message_ranks_tag_chat_rename_1=Please write the &6tag &7you'd like to use and &6submit&7. +spigot_message_ranks_tag_chat_rename_1=Please enter the &6tag &7you'd like to use and &6submit&7. spigot_message_ranks_tag_chat_rename_2=Input &cclose &7to cancel or wait &c30 seconds&7. -spigot_message_ranks_tag_chat_cancelled=Rename tag &cclosed&7, nothing got changed! +spigot_message_ranks_tag_chat_cancelled=Rename tag &cclosed&7, nothing was changed! ## SellAll Messages -spigot_message_sellall_auto_already_enabled=Sellall Auto already enabled. -spigot_message_sellall_auto_already_disabled=SellAll Auto already disabled. -spigot_message_sellall_auto_disabled=SellAll Auto disabled with success. +spigot_message_sellall_auto_already_enabled=Sellall AutoSell was already enabled. +spigot_message_sellall_auto_already_disabled=SellAll AutoSell wasg already disabled. +spigot_message_sellall_auto_disabled=AutoSell has been disabled. spigot_message_sellall_auto_disabled_cant_use=Sorry, you need to enable AutoSell to use this. -spigot_message_sellall_auto_enabled=SellAll Auto enabled with success. -spigot_message_sellall_auto_perusertoggleable_enabled=Sellall Auto perUserToggleable enabled with success. -spigot_message_sellall_auto_perusertoggleable_disabled=Sellall Auto perUserToggleable disabled with success. -spigot_message_sellall_auto_perusertoggleable_already_enabled=Sellall Auto perUserToggleable already enabled. -spigot_message_sellall_auto_perusertoggleable_already_disabled=Sellall Auto perUserToggleable already disabled. +spigot_message_sellall_auto_enabled=AutoSell has been enabled. +spigot_message_sellall_auto_perusertoggleable_enabled=Sellall AutoSell perUserToggleable is enabled. +spigot_message_sellall_auto_perusertoggleable_disabled=Sellall AutoSell perUserToggleable is disabled. +spigot_message_sellall_auto_perusertoggleable_already_enabled=Sellall AutoSell perUserToggleable already enabled. +spigot_message_sellall_auto_perusertoggleable_already_disabled=Sellall AutoSell perUserToggleable already disabled. spigot_message_sellall_boolean_input_invalid=The boolean value isn't valid (Valid values are True or False). spigot_message_sellall_cant_find_item_config=Sorry, can't find your item in the config. spigot_message_sellall_currency_chat_1=&3Started setup of new currency for SellAll! @@ -238,7 +248,7 @@ spigot_message_sellall_currency_chat_4=Type the &aCurrency name &7to set the new spigot_message_sellall_currency_edit_success=SellAll Currency edited with success. spigot_message_sellall_currency_not_found=Sorry, currency not found. spigot_message_sellall_hand_disabled=SellAll Hand disabled with success. -spigot_message_sellall_hand_enabled=Sellall Hand enabled with success. +spigot_message_sellall_hand_enabled=SellAll Hand enabled with success. spigot_message_sellall_hand_is_disabled=SellAll Hand is disabled. spigot_message_sellall_item_add_success=Item added with success. spigot_message_sellall_item_already_added=You've already added this item, please use the edit command instead. diff --git a/prison-core/src/main/resources/lang/spigot/fr_FR.properties b/prison-core/src/main/resources/lang/spigot/fr_FR.properties index 3386e0a61..57a4eadbb 100644 --- a/prison-core/src/main/resources/lang/spigot/fr_FR.properties +++ b/prison-core/src/main/resources/lang/spigot/fr_FR.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=6 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/spigot/pt_PT.properties b/prison-core/src/main/resources/lang/spigot/pt_PT.properties index 2c2272449..198f1828d 100644 --- a/prison-core/src/main/resources/lang/spigot/pt_PT.properties +++ b/prison-core/src/main/resources/lang/spigot/pt_PT.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=2 messages__auto_refresh=true diff --git a/prison-core/src/main/resources/lang/spigot/zh-CN.properties b/prison-core/src/main/resources/lang/spigot/zh-CN.properties index 0f067c215..5cb478919 100644 --- a/prison-core/src/main/resources/lang/spigot/zh-CN.properties +++ b/prison-core/src/main/resources/lang/spigot/zh-CN.properties @@ -49,6 +49,16 @@ ## /prison support submit. ## +# NOTE: If you need to eliminate a message, leave an empty String after the equal sign `=`, or +# use the key word `*none*`. Prison will not insert element or send a message if +# these values are found. +# Example: `core_text__from_now=from now` use either `core_text__from_now=` or `core_text__from_now=*none*` +# +# NOTE: Specific to the `core_output__` messages, `/prison reload locales` cannot reload them because +# these are a very low level static component of the fallback messaging system within Prison. +# You will have to restart the server if you make any changes to the messages with these prefixes. +# + messages__version=5 messages__auto_refresh=true 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 6875c4201..a1d5ca6d6 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java @@ -295,10 +295,23 @@ public double getConfigDouble( String key, double defaultValue ) { } @Override - public List getConfigStringArray( String key ) { + public List getConfigStringArray( String key ) { return new ArrayList(); } + /** + *

Given the path to a hash, this will return all of the keys within + * the hash at the root level. It will not traverse deeper. + * The list of keys can then be used to access all of the values. + *

+ * + */ + @Override + public List getConfigHashKeys(String hashPrefix) { + return new ArrayList(); + } + + @Override public boolean isWorldExcluded( String worldName ) { return false; @@ -421,6 +434,13 @@ public void saveResource( String string, boolean replace ) { } + + @Override + public boolean isMineNameValid(String mineName) { + return false; + } + + @Override public String getMinesListString() { return ""; @@ -533,4 +553,13 @@ public int getMinY() { public int getMaxY() { return 255; } + + public String getLadderByFileName(String name) { + return "default"; + } + + + public String getRankByFileName(String name) { + return "a"; + } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/discord/PrisonSupportFilesTest.java b/prison-core/src/test/java/tech/mcprison/prison/discord/PrisonSupportFilesTest.java new file mode 100644 index 000000000..69d495bdd --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/discord/PrisonSupportFilesTest.java @@ -0,0 +1,49 @@ +package tech.mcprison.prison.discord; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class PrisonSupportFilesTest + extends PrisonSupportFiles +{ + + @Test + public void test() { + + String t1 = "This is a test"; + String r1 = "This is a test\n"; + + assertEquals(r1, convertColorCodes(t1) ); + + + String t2 = "&3This is a test"; + String r2 = "This is a test\n"; + + assertEquals(r2, convertColorCodes(t2) ); + + + String t3 = "&3This is a &1test"; + String r3 = "This is a " + + "test\n"; + + assertEquals(r3, convertColorCodes(t3) ); + + + String t4 = "&3This is a &1test & sample"; + String r4 = "This is a " + + "test & sample\n"; + + assertEquals(r4, convertColorCodes(t4) ); + + + String t5 = "&3This is a &1test & a&r fun &1sample"; + String r5 = "This is a " + + "test & a" + + " fun sample\n"; + + assertEquals(r5, convertColorCodes(t5) ); + + } + +} 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 da33a9961..d827c336d 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 @@ -38,6 +38,7 @@ import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.modules.ModuleManager; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.store.Database; import tech.mcprison.prison.util.Location; @@ -49,7 +50,9 @@ * @author The MC-Prison Team */ public class PrisonMines extends Module { - public static final String MODULE_NAME = "Mines"; + + public static final String MODULE_NAME = ModuleManager.MODULE_NAME_MINES; +// public static final String MODULE_NAME = "Mines"; private static PrisonMines i = null; private MinesConfig config; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java index f4ae83f64..61b967958 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java @@ -340,7 +340,12 @@ public void setBlockCommand(CommandSender sender, prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); } - + if ( block == null || prisonBlock == null ) { + + sender.sendMessage( + String.format( "Invalid blockk name: [%s]", block ) ); + return; + } // Change behavior: If trying to change a block that is not in the mine, then instead add it: if (!m.isInMine(prisonBlock)) { 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 505fbcae0..35512e819 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 @@ -37,6 +37,7 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; @@ -897,6 +898,8 @@ private ChatDisplay mineInfoDetails( CommandSender sender, boolean isMineStats, DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); ChatDisplay chatDisplay = new ChatDisplay("&bMine: &3" + m.getName()); + + chatDisplay.addSupportHyperLinkData( "Mine %s", m.getName() ); { RowComponent row = new RowComponent(); @@ -1882,7 +1885,7 @@ public void skipResetCommand(CommandSender sender, @Command(identifier = "mines set resetTime", permissions = "mines.set", description = "Set a mine's auto reset time as expressed in seconds.") public void resetTimeCommand(CommandSender sender, - @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, + @Arg(name = "mineName", description = "The name of the mine to edit, or '*all' to apply to all mines.") String mineName, @Arg(name = "time", description = "Time in seconds for the mine to auto reset. " + "With a minimum value of "+ MineData.MINE_RESET__TIME_SEC__MINIMUM + " seconds. " + "Using '*disable*' will turn off the auto reset. Use of " @@ -1915,7 +1918,7 @@ else if ( "*default*".equalsIgnoreCase( time ) ) { return; } } - if ( resetTime < MineData.MINE_RESET__TIME_SEC__MINIMUM ) { + if ( !"*disable*".equalsIgnoreCase( time ) && resetTime < MineData.MINE_RESET__TIME_SEC__MINIMUM ) { Output.get().sendWarn( sender, "&7Invalid resetTime value for &b%s&7. Must be an integer value of &b%d&7 or greater. [&b%d&7]", mineName, MineData.MINE_RESET__TIME_SEC__MINIMUM, resetTime ); @@ -2775,25 +2778,41 @@ public void backupMineCommand(CommandSender sender, } - @Command(identifier = "mines set tracer", permissions = "mines.set", - description = "Clear the mine and set a tracer around the outside") + @Command(identifier = "mines set tracer", + description = "Clears the mine of all blocks and sest a tracer of " + + "pink glass blocks around the outside", + permissions = "mines.set") public void setTracerCommand(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 set the tracer in.") String mineName, + @Arg(name = "options", def = "outline", + description = "Options to control how the tracer is set. " + + "Defaults to 'outline' which draws a pink glass block around the edges of the mine. " + + "The option 'corners' will only place blocks within the corners of the mine. " + + "The option of 'clear' will just clear the mine and will not place any tracers. " + + "[outline corners clear]") String option ) { if (!performCheckMineExists(sender, mineName)) { return; } + MineResetType resetType = MineResetType.fromString(option); + + if ( resetType != MineResetType.corners && resetType != MineResetType.clear ) { + resetType = MineResetType.tracer; + } + + 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; } - mine.enableTracer(); + mine.enableTracer( resetType ); } @@ -3311,6 +3330,53 @@ else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.get } } + + + @Command(identifier = "mines top", + description = "TP to the top of the current mine. Will default to the mine's " + + "spawn location if set, but can specify the target [spawn, mine]. If not in a " + + "mine, then it will be the same as '/mtp' where it will take you to a mine that " + + "is linked to your current rank. This command has no options.", + aliases = "mtop", + altPermissions = {"access-by-rank", "mines.tp"}) + public void mineTpTop(CommandSender sender ) { + + + Player player = getPlayer( sender ); + //oboolean isOp = sender.isOp(); + + + if ( player == null || !player.isOnline() ) { + + teleportPlayerMustBeIngameMsg( sender ); + return; + } + + + PrisonMines pMines = PrisonMines.getInstance(); + + Mine mine = pMines.findMineLocationExact( player.getLocation() ); + + + if ( mine != null ) { + if ( mine.isVirtual() ) { + teleportCannotUseVirtualMinesMsg( sender ); + return; + } + else { + + mineTp( sender, mine.getName(), "", "spawn"); + } + } + else { + // Player is not in a mine, so issue `/mtp` command for them: + mineTp( sender, "", "", ""); + } + + + + } + private void teleportPlayer( Player player, Mine mine, String target ) { if ( Prison.get().getPlatform().getConfigBooleanFalse( "prison-mines.tp-warmup.enabled" ) ) { 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 214b745f6..d397bfdc6 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 @@ -596,8 +596,11 @@ public void generateBlockListAsync() { boolean isEdge = xEdge && yEdge || xEdge && zEdge || yEdge && zEdge; + boolean isCorner = xEdge && yEdge && zEdge; + Location targetBlock = new Location(world, x, y, z); targetBlock.setEdge( isEdge ); + targetBlock.setCorner( isCorner ); // MineTargetBlock mtb = null; @@ -1269,8 +1272,11 @@ public List refreshAirCountSyncTaskBuildLocations() { boolean isEdge = xEdge && yEdge || xEdge && zEdge || yEdge && zEdge; + boolean isCorner = xEdge && yEdge && zEdge; + Location targetBlock = new Location(world, x, y, z); targetBlock.setEdge( isEdge ); + targetBlock.setCorner( isCorner ); locations.add( targetBlock ); @@ -1790,11 +1796,12 @@ private void constraintsApplyMin( PrisonBlockStatusData block ) /** * This clears the mine, then provides particle tracers around the outer corners. + * @param resetType */ - public void enableTracer() { + public void enableTracer(MineResetType resetType) { // First clear the mine: - clearMine( true ); + clearMine( resetType ); // Prison.get().getPlatform().enableMineTracer( // getWorldName(), @@ -1817,7 +1824,7 @@ public void enableTracer() { public void adjustSize( Edges edge, int amount ) { // First clear the mine: - clearMine( false ); + clearMine( MineResetType.clear ); // if amount is zero, then just refresh the liner: @@ -1852,7 +1859,7 @@ else if ( amount > 0 ) { } // Finally trace the mine: - clearMine( true ); + clearMine( MineResetType.tracer ); } @@ -1863,10 +1870,10 @@ public void moveMine( Edges edge, int amount ) { } - public void clearMine( boolean tracer ) { + public void clearMine( MineResetType resetType ) { MineTracerBuilder tracerBuilder = new MineTracerBuilder(); - tracerBuilder.clearMine( (Mine) this, tracer ); + tracerBuilder.clearMine( (Mine) this, resetType ); } @@ -1885,7 +1892,7 @@ private void addMineTargetPrisonBlock( PrisonBlockStatusData block, Location tar MineTargetPrisonBlock mtpb = new MineTargetPrisonBlock( block, getWorld().get(), targetBlock.getBlockX(), targetBlock.getBlockY(), targetBlock.getBlockZ(), - targetBlock.isEdge() ); + targetBlock.isEdge(), targetBlock.isCorner() ); synchronized ( getMineStateMutex() ) { 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 index 7873665d8..c34a3d527 100644 --- 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 @@ -41,12 +41,21 @@ public enum BlockEventType { RevEnExplosion, RevEnJackHammer, + ExplosionTriggerEvent, + LayerTriggerEvent, + NukeTriggerEvent, + eventTypeAll( all ), eventBlockBreak( blockBreak ), eventTEXplosion( TEXplosion ), eventRevEnExplosion( RevEnExplosion ), - eventRevEnJackHammer( RevEnJackHammer ), + eventRevEnJackHammer( RevEnJackHammer ), + + XPrisonExplosionTriggerEvent( ExplosionTriggerEvent ), + XPrisonLayerTriggerEvent( LayerTriggerEvent ), + XPrisonNukeTriggerEvent( NukeTriggerEvent ), + ; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java index 7d61ecec1..250e24613 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineLinerBuilder.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.BlockFace; +import tech.mcprison.prison.internal.block.MineResetType; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineLinerData.LadderType; @@ -192,7 +193,7 @@ public MineLinerBuilder( Mine mine, Edges edge, LinerPatterns pattern, boolean i this.isForced = isForced; if ( pattern != null ) { - mine.enableTracer(); + mine.enableTracer( MineResetType.clear ); generatePattern( edge ); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java index d5dcee4b5..5d21a7fe6 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineMover.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.mines.features; +import tech.mcprison.prison.internal.block.MineResetType; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.util.Bounds; @@ -14,7 +15,7 @@ public MineMover() { public void moveMine( Mine mine, Edges edge, int amount ) { - mine.clearMine( false ); + mine.clearMine( MineResetType.clear ); new MineLinerBuilder( mine, Edges.top, LinerPatterns.repair, false ); new MineLinerBuilder( mine, Edges.bottom, LinerPatterns.repair, false ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java index 84737cb1b..6f2059a17 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java @@ -45,7 +45,7 @@ public static TracerType fromString( String type ) { } } - public void clearMine( Mine mine, boolean tracer ) { + public void clearMine( Mine mine, MineResetType resetType ) { if ( mine == null ) { Output.get().logError(" #### Null MINE? ###"); @@ -56,7 +56,7 @@ public void clearMine( Mine mine, boolean tracer ) { return; } - MineResetType resetType = tracer ? MineResetType.tracer : MineResetType.clear; +// MineResetType resetType = tracer ? MineResetType.tracer : MineResetType.clear; MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( mine, resetType ); resetTask.submitTaskAsync(); 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 91e6ea570..f53f77ae6 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 @@ -45,6 +45,7 @@ import tech.mcprison.prison.placeholders.PlaceholderAttributeBar; import tech.mcprison.prison.placeholders.PlaceholderAttributeNumberFormat; import tech.mcprison.prison.placeholders.PlaceholderAttributeText; +import tech.mcprison.prison.placeholders.PlaceholderAttributeTime; import tech.mcprison.prison.placeholders.PlaceholderIdentifier; import tech.mcprison.prison.placeholders.PlaceholderManager; import tech.mcprison.prison.placeholders.PlaceholderManager.PlaceholderFlags; @@ -775,6 +776,8 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); PlaceholderAttributeText attributeText = identifier.getAttributeText(); + PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); + int sequence = identifier.getSequence(); @@ -791,6 +794,7 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { if ( mine != null || placeHolderKey.getPlaceholder().hasFlag( PlaceholderFlags.PLAYERBLOCKS ) || placeHolderKey.getPlaceholder().hasFlag( PlaceholderFlags.MINEPLAYERS )) { + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); // DecimalFormat fFmt = Prison.get().getDecimalForma("#,##0.00"); @@ -828,6 +832,10 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { results = attributeNFormat.format( (long) mine.getResetTime() ); } + else if ( attributeTime != null ) { + + results = attributeTime.format( (long) mine.getResetTime() ); + } else { results = iFmt.format( mine.getResetTime() ); @@ -846,6 +854,10 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { results = attributeNFormat.format( (long) mine.getResetTime() ); } + else if ( attributeTime != null ) { + + results = attributeTime.format( (long) mine.getResetTime() ); + } else { double timeMif = mine.getResetTime(); @@ -866,6 +878,10 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { results = attributeNFormat.format( (long) mine.getRemainingTimeSec() ); } + else if ( attributeTime != null ) { + + results = attributeTime.format( (long) mine.getResetTime() ); + } else { results = dFmt.format( mine.getRemainingTimeSec() ); } diff --git a/prison-misc/build.gradle b/prison-misc/build.gradle new file mode 100644 index 000000000..5d17da6d5 --- /dev/null +++ b/prison-misc/build.gradle @@ -0,0 +1,91 @@ +/* + * Prison is a Minecraft plugin for the prison game mode. + * Copyright (C) 2017 The Prison Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +group 'tech.mcprison' + +apply plugin: 'java' + +compileJava.options.encoding = 'UTF-8' +compileTestJava.options.encoding = "UTF-8" + +//sourceCompatibility = 1.8 + + +// https://www.spigotmc.org/wiki/spigot-gradle/ + + +repositories { + mavenCentral() + + + maven { + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + + // As of Gradle 5.1, you can limit this to only those + // dependencies you expect from it + content { + includeGroup 'org.bukkit' + includeGroup 'org.spigotmc' + } + } + /* + As Spigot-API depends on the BungeeCord ChatComponent-API, + we need to add the Sonatype OSS repository, as Gradle, + in comparison to maven, doesn't want to understand the ~/.m2 + directory unless added using mavenLocal(). Maven usually just gets + it from there, as most people have run the BuildTools at least once. + This is therefore not needed if you're using the full Spigot/CraftBukkit, + or if you're using the Bukkit API. + */ + maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + maven { url = 'https://oss.sonatype.org/content/repositories/central' } + + // mavenLocal() // This is needed for CraftBukkit and Spigot. + maven { + url "https://mvnrepository.com/artifact" + } + + // maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } + + + // maven { url = "https://maven.enginehub.org/repo/" } +} + + + +dependencies { +// implementation project(':prison-core') +// implementation project(':prison-mines') +// implementation project(':prison-ranks') +// implementation project(':prison-sellall') + + + // https://mvnrepository.com/artifact/org.jetbrains/annotations + implementation 'org.jetbrains:annotations:24.0.1' + + + compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + + + + testImplementation group: 'junit', name: 'junit', version: '4.12' + +} + + + diff --git a/prison-misc/src/main/java/su/nightexpress/coinsengine/api/CoinsEngineAPI.java b/prison-misc/src/main/java/su/nightexpress/coinsengine/api/CoinsEngineAPI.java new file mode 100644 index 000000000..70bac8065 --- /dev/null +++ b/prison-misc/src/main/java/su/nightexpress/coinsengine/api/CoinsEngineAPI.java @@ -0,0 +1,72 @@ +package su.nightexpress.coinsengine.api; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import su.nightexpress.coinsengine.api.currency.Currency; + +public class CoinsEngineAPI { + + //public static final CoinsEngine PLUGIN = CoinsEngine.getPlugin(CoinsEngine.class); + + public static double getBalance(@NotNull Player player, @NotNull Currency currency) { + return 0d; + } + + public static void addBalance(@NotNull Player player, @NotNull Currency currency, double amount) { + + } + + public static void setBalance(@NotNull Player player, @NotNull Currency currency, double amount) { + + } + + public static void removeBalance(@NotNull Player player, @NotNull Currency currency, double amount) { + + } + +// @NotNull +// public static CoinsUser getUserData(@NotNull Player player) { +// return PLUGIN.getUserManager().getUserData(player); +// } +// +// @Nullable +// public static CoinsUser getUserData(@NotNull String name) { +// return PLUGIN.getUserManager().getUserData(name); +// } +// +// @NotNull +// public static CompletableFuture getUserDataAsync(@NotNull String name) { +// return PLUGIN.getUserManager().getUserDataAsync(name); +// } +// +// @Nullable +// public static CoinsUser getUserData(@NotNull UUID uuid) { +// return PLUGIN.getUserManager().getUserData(uuid); +// } +// +// @NotNull +// public static CompletableFuture getUserDataAsync(@NotNull UUID uuid) { +// return PLUGIN.getUserManager().getUserDataAsync(uuid); +// } + + @Nullable + public static Currency getCurrency(@NotNull String id) { + return null; + } + + public static boolean hasCurrency(@NotNull String id) { + return false; + } + +// @NotNull +// public static UserManager getUserManager() { +// return PLUGIN.getUserManager(); +// } +// +// @NotNull +// public static CurrencyManager getCurrencyManager() { +// return PLUGIN.getCurrencyManager(); +// } +} diff --git a/prison-misc/src/main/java/su/nightexpress/coinsengine/api/currency/Currency.java b/prison-misc/src/main/java/su/nightexpress/coinsengine/api/currency/Currency.java new file mode 100644 index 000000000..0123349c8 --- /dev/null +++ b/prison-misc/src/main/java/su/nightexpress/coinsengine/api/currency/Currency.java @@ -0,0 +1,88 @@ +package su.nightexpress.coinsengine.api.currency; + +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public interface Currency { + + default boolean isUnlimited() { + return true; + } + + default boolean isLimited() { + return false; + } + + default boolean isInteger() { + return false; + } + + default double fine(double amount) { + return 0d; + } + + default double limit(double amount) { + return 0d; + } + + default double fineAndLimit(double amount) { + return 0d; + } + + @NotNull + default String getPermission() { + return ""; + } + + @NotNull + default String formatValue(double balance) { + return ""; + } + + @NotNull + default String format(double balance) { + return ""; + } + + @NotNull String getId(); + + @NotNull String getName(); + + //void setName(@NotNull String name); + + @NotNull String getSymbol(); + + @NotNull String getFormat(); + + //void setSymbol(@NotNull String symbol); + + @NotNull String[] getCommandAliases(); + + @NotNull ItemStack getIcon(); + + //void setCommandAliases(@NotNull String... aliases); + + boolean isDecimal(); + + //void setDecimal(boolean decimal); + + boolean isPermissionRequired(); + + //void setPermissionRequired(boolean permissionRequired); + + boolean isTransferAllowed(); + + double getMinTransferAmount(); + + //void setTransferAllowed(boolean transferAllowed); + + double getStartValue(); + + //void setStartValue(double startValue); + + double getMaxValue(); + + //void setMaxValue(double maxValue); + + boolean isVaultEconomy(); +} 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 c42474100..80527e11c 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 @@ -28,6 +28,7 @@ import tech.mcprison.prison.integration.IntegrationType; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.localization.LocaleManager; +import tech.mcprison.prison.modules.ModuleManager; import tech.mcprison.prison.modules.ModuleStatus; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; @@ -55,7 +56,8 @@ public class PrisonRanks extends PrisonRanksMessages { - public static final String MODULE_NAME = "Ranks"; + public static final String MODULE_NAME = ModuleManager.MODULE_NAME_RANKS; +// public static final String MODULE_NAME = "Ranks"; /* * Fields & Constants */ diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommands.java index 4e166ba48..abd6901ac 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommands.java @@ -1,16 +1,20 @@ package tech.mcprison.prison.ranks.commands; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.backups.PrisonBackups; +import tech.mcprison.prison.backups.PrisonBackups.BackupTypes; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.BulletedListComponent; import tech.mcprison.prison.output.ChatDisplay; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.PlayerRankRefreshTask; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; +import tech.mcprison.prison.ranks.managers.RankManager; /** * @author Faizaan A. Datoo @@ -94,7 +98,57 @@ public void ladderRemove(CommandSender sender, @Arg(name = "ladderName") String @Command(identifier = "ranks ladder list", description = "Lists all rank ladders.", onlyPlayers = false, permissions = "ranks.ladder") public void ladderList(CommandSender sender) { - ChatDisplay display = new ChatDisplay("Ladders"); + + ChatDisplay display = getLadderList(); + +// ChatDisplay display = new ChatDisplay("Ladders"); +// +// display.addSupportHyperLinkData( "Ladder List" ); +// +// BulletedListComponent.BulletedListBuilder list = +// new BulletedListComponent.BulletedListBuilder(); +// +//// DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.0000" ); +// +//// String header = String.format( +//// "&d%-12s %16s %5s %12s %12s", +//// "Ladder", +//// "Rank Cost Mult", +//// "Ranks", +//// "First Rank", +//// "Last Rank" +//// ); +// +// list.add( PrisonRanks.getInstance().getLadderManager().printRankLadderInfoHeader() ); +// +// for (RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders()) { +// +//// int rankCount = ladder.getRanks() == null ? 0 : ladder.getRanks().size(); +//// +//// Rank firstRank = rankCount == 0 ? null : ladder.getRanks().get(0); +//// Rank lastRank = rankCount == 0 ? null : ladder.getRanks().get( rankCount - 1 ); +//// +//// String ladderInfo = String.format( +//// "&7%-12s %16s %4d %-12s %-12s", +//// ladder.getName(), +//// dFmt.format( ladder.getRankCostMultiplierPerRank() ), +//// rankCount, +//// firstRank.getName(), +//// lastRank.getName() +//// ); +// +// list.add( PrisonRanks.getInstance().getLadderManager().printRankLadderInfoDetail( ladder ) ); +// } +// +// display.addComponent(list.build()); + + display.send(sender); + } + + public ChatDisplay getLadderList() { + ChatDisplay display = new ChatDisplay("Ladders"); + + display.addSupportHyperLinkData( "Ladder List" ); BulletedListComponent.BulletedListBuilder list = new BulletedListComponent.BulletedListBuilder(); @@ -132,8 +186,8 @@ public void ladderList(CommandSender sender) { } display.addComponent(list.build()); - - display.send(sender); + + return display; } // @Command(identifier = "ranks ladder listranks", description = "Lists the ranks within a ladder.", @@ -316,12 +370,44 @@ public void ladderRemoveRank(CommandSender sender, @Command( identifier = "ranks ladder rankCostMultiplier", - description = "Sets or removes a ladder's Rank Cost Multiplier. Setting the " + - "value to zero will remove the multiplier from the calculations. The " + - "Rank Cost Multiplier from all ladders a player has active, will be " + - "summed together and applied to the cost of all of their ranks. The Rank " + - "Cost Multiplier represents a percentage, and can be either postive or " + - "negative. ", + description = "Sets a ladder's rank cost multiplier which is used to calculate " + + "a rank's cost on ladders that have them enabled. " + + "Setting the value to zero will remove that ladder's rank multiplier from " + + "the calculations. " + + "Rank Cost Multiplier represents a percentage, and can be either postive or " + + "negative, and is multiplied by the rank's position (1's based). " + + "This means that for ladders have have a rank cost multiplier, the " + + "multiplier increases by the rank's position, such that if the prestige " + + "ladder has a ranks cost multiplier of 0.1, the P1=0.1, P2=0.2, P3=0.3, etc... {br}" + + + "All rank cost multipliers for the player's rank on that ladder, are " + + "combined from all ladders the player is on, " + + "then this value is added to a value of 1.0 before being multiplied to the rank cost. " + + "This will result in a progressively more expensive rank cost for the " + + "player as they advance on multiple ladders. " + + "If a ladder has 'applyRankCostMultiplier' disabled, then rank costs on that " + + "ladder will not use the player's combined rank cost multiplier. {br}" + + + "This calculates " + + "what a player would have to pay when ranking up. " + + "It should be understood that a ladder can contribute to the total " + + "ranks multiplier, but yet it could ignore the ranks multiplier when " + + "calculating the rank costs for that ladder. {br}" + + + "Example of this kind of setup would be to have the " + + "default ladder apply the rank cost multiplier to its rank's costs, " + + "but yet have the default ladder set it's rank cost multiplier to a value of 0.0. " + + "Then have the prestige ladder ignore " + + "them, but have the prestige ladder contribute to the global rank " + + "cost multipliers. This configuration will result in rank costs increasing " + + "for the default ladder's ranks, as the player increases their prestige ranks. " + + "But yet the prestiges ladder rank costs will not be impacted " + + "by the rank cost multipliers. Using the example above for p1, p2, p3, etc, " + + "the rank costs on the default ladder will increase by 10 percent each time " + + "the player prestiges. At a 10% increase, the default rank costs will be " + + "twice as expensive when the are at P10, compared to when they were at " + + "p0 (no prestige rank)." + , onlyPlayers = false, permissions = "ranks.ladder" ) public void ladderSetRankCostMultiplier( CommandSender sender, @Arg( name = "ladderName" ) String ladderName, @@ -379,15 +465,15 @@ public void ladderSetRankCostMultiplier( CommandSender sender, @Command( identifier = "ranks ladder applyRankCostMultiplier", - description = "Controls if the rank costs multiplier should apply to the" + - "ranks on this ladder. If the ladder has a rank cost multipiler " + - "enabled, this setting will not effect its contribution to other " + - "the multiplier.", + description = "Controls if the rank costs multiplier should apply to the " + + "ranks on this ladder. This is an 'ON' or 'OFF' situation for the whole " + + "ladder, where the Rank Cost Multiplier will be ignored for a ladder " + + "if this is disabled.", onlyPlayers = false, permissions = "ranks.ladder" ) public void ladderApplyRankCostMultiplier( CommandSender sender, @Arg( name = "ladderName" ) String ladderName, @Arg( name = "applyRankCostMultiplier", def = "apply", - description = "Applies or disables the ranks on this ladder " + description = "Applies or disables the ranks on this ladder " + "from applying the rank multiplier to the rank cost for players." ) String applyRankCostMultiplier ) @@ -433,4 +519,118 @@ public void ladderApplyRankCostMultiplier( CommandSender sender, } + @Command( identifier = "ranks ladder resetRankCosts", + description = "For a given ladder, this command will reset all rank costs " + + "based upon a formula, where each rank is progressivly more " + + "expensive. " + + "This allow easier adjustments to many ranks at the same time. " + + "The ranks within this ladder will not be changed, and they will be " + + "processed in the same order in which they are listed with the " + + "command: '/ranks list '.", + onlyPlayers = false, permissions = "ranks.ladder" ) + public void ladderResetRankCosts(CommandSender sender, + @Arg(name = "ladderName") String ladderName, + + @Arg(name = "initialCost", + def = "1000000000", verifiers = "min[1]", + description = "The 'initialCost' will set the cost of the first rank on " + + "this ladder. All other rank costs will be based upon this " + + "value. The default value is 1_000_000_0000." + ) double initialCost, + @Arg(name = "addMult", def = "1", verifiers = "min[1]", + description = "This is an 'additional multiplier' for all ranks on the ladder, " + + "with the default value of 1. The cost for each rank is based upon " + + "the initial rank cost, times the rank's level. So the default ranks " + + "named 'C', or 'p3', since both are the third rank on their ladders, " + + "will be 3 times the cost of the first ranks, 'A' or 'p1', with this " + + "additional multiplier being multiplied against that value. " + + "So for default values for a rankk in the third position, " + + "with a 1.75 multipler will have a " + + "cost = 1_000_000_000 * 3 * 1.75.") double addMult, + @Arg(name = "exponent", def = "1", verifiers = "min[0.00001]", + description = "See the cost formula for the 'addMult' parameter. " + + "This parameter adds an exponent to the formula. For a linear " + + "rank cost, use a value of 1.0 for this parameter. Use a value " + + "greater than 1.0, such as 1.2 for slightly more agressive cost " + + "calculation. Since cost is a IEEE double, there is a risk of " + + "lost precision with numbers greater than 16 digits. " + + "cost = (initialCost * rankPosition * addMult)^exponent.") + double exponent ) { + + + LadderManager lm = PrisonRanks.getInstance().getLadderManager(); + RankManager rm = PrisonRanks.getInstance().getRankManager(); + + RankLadder ladder = lm.getLadder(ladderName); + + if ( ladder == null ) { + ladderDoesNotExistsMsg( sender, ladderName ); + return; + } + + + if ( exponent <= 0 ) { + sender.sendMessage("Error: ranks ladder resetRankCosts: Exponent parameter must be greater than zero."); + return; + } + + // Force a backup: + PrisonBackups prisonBackup = new PrisonBackups(); + + String backupComment = String.format( + "Resetting all rank costs on ladder %s.", + ladder.getName() ); + String message = prisonBackup.startBackup( BackupTypes.auto, backupComment ); + + sender.sendMessage( message ); + sender.sendMessage( "Forced a Backup of prison configs prior to changing rank costs." ); + + + int ranksChanged = 0; + + int i = 1; + for (Rank rank : ladder.getRanks() ) { + + double cost = Math.pow(initialCost * i++ * addMult, exponent ); + + if ( rank.getRawRankCost() != cost ) { + rank.setRawRankCost( cost ); + + rm.saveRank( rank ); + + ranksChanged++; + } + + } + + if ( ranksChanged > 0 ) { + // Reload the placeholders: + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + String msg = String.format( + "Done resetting all rank costs on the '%s' ladder. " + + "There were %d ranks that had cost changes.", + ladder.getName(), + ranksChanged ); + + Output.get().logInfo( msg ); + } + +// for ( int i = 0; i < prestigeRanks; i++ ) { +// String name = "P" + (i + 1); +// String tag = "&5[&d+" + (i > 0 ? i + 1 : "" ) + "&5]"; +// double cost = prestigeCost * (i + 1) * prestigeMult; +// +// // Only add prestige ranks if they do not already exist: +// if ( PrisonRanks.getInstance().getRankManager().getRank( name ) == null ) { +// +// createRank(sender, name, cost, LadderManager.LADDER_PRESTIGES, tag, "noPlaceholderUpdate"); +// prestigesCount++; +// } +// } + + + } + + } 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 71abf642c..6ca277370 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 @@ -455,7 +455,19 @@ private boolean rankUpPrivate(CommandSender sender, String playerName, String la RankPlayer rankPlayer = getRankPlayer( sender, player.getUUID(), player.getName() ); + + + PlayerRank rankCurrent = rankPlayer.getPlayerRank(ladder); + + + // If the player has a rank on the target ladder, mmake sure the next rank is not null + if ( rankCurrent != null && rankCurrent.getRank().getRankNext() == null ) { + rankupAtLastRankMsg(sender); + return false; + } + // If at last rank on ladder, then cannot /rankup +// if ( rankPlayer.getran) // Get the player's next rank on default ladder, or if at end then it will return the next 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 47b28ea24..3dcb370cd 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 @@ -216,20 +216,46 @@ public boolean createRank(CommandSender sender, } - @Command(identifier = "ranks autoConfigure", description = "Auto configures Ranks and Mines using " + + @Command(identifier = "ranks autoConfigure", + description = "Auto configures Ranks, Mines, and Prestiges using " + "single letters A through Z for both the rank and mine names. 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. AutoConfigure will try to merge any preexsiting ranks " + - "and mines, but you must use the 'force' keyword in 'options'. Force will replace all blocks " + - "in preexisting " + - "mines. To keep preexisting blocks, use 'forceKeepBlocks' with the 'force' option. " + - "Default values [full price=50000 mult=1.5]", + "generated, they will also be linked together automatically. Prestige ranks will " + + "also be auto generated with a default of 25 that will be created. {br}" + + "To set the starting price use " + + "'price=x'. To set multiplier 'mult=x'. {br}" + + "AutoConfigure will try to merge any preexsiting ranks " + + "and mines, but you must use the 'force' keyword in 'options' and force will " + + "replace all blocks in preexisting " + + "mines. To keep preexisting blocks, use 'forceKeepBlocks' with the 'force' option. {br}" + + + "The option 'full' will enable ranks, mines, and prestiges. No options will default to 'full'. " + + "The options 'ranks', 'mines', and 'prestiges' will enable each of these if they are listed. " + + "So using just 'mines' will only generate mines and no ranks or prestiges." + + + "The option 'prestiges=x' will set how many initial prestige ranks to create. " + + "The option `prestigeCost=x` sets the initial cost for P1; default value is 1_000_000_000. " + + "The option 'prestigeMult=x' is an additional multiplier for presetige ranks, with the " + + "default value of 1. The cost for each prestige rank is based upon the initial " + + "presetigeCost, times the prestige level so p3 will be 3 times the cost of p1 with the " + + "prestige multiplier will multiplied against that value. So for default values " + + " with a 1.75 multiplier p3 cost = 1_000_000_000 * 3 * 1.75. " + + "Default values [full price=50000 mult=1.5 prestiges=25 presetigeCost=1000000000 " + + "prestigeMult=1] {br}" + + + "Example of just adding more prestige ranks using the other default values: " + + "'/ranks autoConfigure force prestiges presetiges=1000', no ranks and no mines will " + + "be created. " + + "Warning: If trying to rerun autoConfigure with existing mines or ranks, then do a " + + "prison backup with this command: '/prison support backup save adding more prestiges'", onlyPlayers = false, permissions = "ranks.set", aliases = {"prison autoConfigure"} ) public void autoConfigureRanks(CommandSender sender, @Wildcard(join=true) @Arg(name = "options", - description = "Options: [full ranks mines price=x mult=x force forceKeepBlocks dontForceLinerWalls dontForceLinerBottoms]", + description = "Options: [full ranks mines prestiges price=x mult=x " + + "prestiges=x prestigeCost=x prestigeMult=x " + + "force forceKeepBlocks " + + "dontForceLinerWalls dontForceLinerBottoms]", def = "full") String options ) { @@ -240,6 +266,9 @@ public void autoConfigureRanks(CommandSender sender, boolean forceLinersWalls = true; boolean forceLinersBottom = true; boolean forceKeepBlocks = false; + int prestigeRanks = 25; + long prestigeCost = 1_000_000_000; + double prestigeMult = 10d; if ( options.contains( "forcekeepblocks" ) ) { @@ -274,9 +303,13 @@ public void autoConfigureRanks(CommandSender sender, autoConfigForceWarningMsg( sender ); } - String optionHelp = "&b[&7full ranks mines price=&dx &7mult=&dx &7force forceKeepBlocks dontForceLinerWalls dontForceLinerBottoms&b]"; + String optionHelp = "&b[&7full ranks mines prestiges price=&dx &7mult=&dx " + + "&7prestiges=&dx &7prestigeCost=&dx &7prestigeMult=&dx " + + "&7force forceKeepBlocks dontForceLinerWalls dontForceLinerBottoms&b]"; boolean ranks = false; boolean mines = false; + boolean prestiges = false; + double startingPrice = 50000; double percentMultipler = 1.5; @@ -292,6 +325,7 @@ public void autoConfigureRanks(CommandSender sender, if ( options.contains( "full" ) ) { ranks = true; mines = true; + prestiges = true; options = options.replace( "full", "" ).trim(); } if ( options.contains( "ranks" ) ) { @@ -302,6 +336,7 @@ public void autoConfigureRanks(CommandSender sender, mines = true; options = options.replace( "mines", "" ).trim(); } + String priceStr = extractParameter("price=", options); if ( priceStr != null ) { @@ -317,6 +352,20 @@ public void autoConfigureRanks(CommandSender sender, } + String prestigeMultStr = extractParameter("prestigeMult=", options); + if ( prestigeMultStr != null ) { + options = options.replace( prestigeMultStr, "" ); + prestigeMultStr = prestigeMultStr.replace( "prestigeMult=", "" ).trim(); + + try { + prestigeMult = Double.parseDouble( prestigeMultStr ); + } + catch ( NumberFormatException e ) { + // Not a valid double number, or price: + } + } + + String multStr = extractParameter("mult=", options); if ( multStr != null ) { options = options.replace( multStr, "" ); @@ -329,6 +378,41 @@ public void autoConfigureRanks(CommandSender sender, // Not a valid double number, or price: } } + + String prestigesStr = extractParameter("prestiges=", options); + if ( prestigesStr != null ) { + options = options.replace( prestigesStr, "" ); + prestigesStr = prestigesStr.replace( "prestiges=", "" ).trim(); + + try { + prestigeRanks = Integer.parseInt( prestigesStr ); + } + catch ( NumberFormatException e ) { + // Not a valid double number, or price: + } + } + + String prestigeCostStr = extractParameter("prestigeCost=", options); + if ( prestigeCostStr != null ) { + options = options.replace( prestigeCostStr, "" ); + prestigeCostStr = prestigeCostStr.replace( "prestigeCost=", "" ).trim(); + + try { + prestigeCost = Long.parseLong( prestigeCostStr ); + } + catch ( NumberFormatException e ) { + // Not a valid double number, or price: + } + } + + + // This has to be checked after prestiges= or this will destroy that config setting: + if ( options.contains( "prestiges" ) ) { + prestiges = true; + options = options.replace( "prestiges", "" ).trim(); + } + + // What's left over, if not just a blank string, must be an error: @@ -491,13 +575,22 @@ public void autoConfigureRanks(CommandSender sender, int prestigesCount = 0; // add in 10 prestiges at 1 billion each: - double prestigeCost = 1000000000; +// double prestigeCost = 1_000_000_000; - for ( int i = 0; i < 10; i++ ) { - String name = "P" + (i + 1); - String tag = "&5[&d+" + (i > 0 ? i + 1 : "" ) + "&5]"; - createRank(sender, name, (prestigeCost * (i + 1) ), LadderManager.LADDER_PRESTIGES, tag, "noPlaceholderUpdate"); - prestigesCount++; + if ( prestiges ) { + + for ( int i = 0; i < prestigeRanks; i++ ) { + String name = "P" + (i + 1); + String tag = "&5[&d+" + (i > 0 ? i + 1 : "" ) + "&5]"; + double cost = prestigeCost * (i + 1) * prestigeMult; + + // Only add prestige ranks if they do not already exist: + if ( PrisonRanks.getInstance().getRankManager().getRank( name ) == null ) { + + createRank(sender, name, cost, LadderManager.LADDER_PRESTIGES, tag, "noPlaceholderUpdate"); + prestigesCount++; + } + } } // If mines were created, go ahead and auto assign blocks to the mines: @@ -517,9 +610,9 @@ public void autoConfigureRanks(CommandSender sender, // Set the prestiges ladder with a 10% base rank cost multiplier double rankCostMultiplier = 0.10; - RankLadder prestiges = PrisonRanks.getInstance().getLadderManager().getLadder( LadderManager.LADDER_PRESTIGES ); - prestiges.setRankCostMultiplierPerRank( rankCostMultiplier ); - PrisonRanks.getInstance().getLadderManager().save( prestiges ); + RankLadder prestigesLadder = PrisonRanks.getInstance().getLadderManager().getLadderPrestiges(); + prestigesLadder.setRankCostMultiplierPerRank( rankCostMultiplier ); + PrisonRanks.getInstance().getLadderManager().save( prestigesLadder ); // Log that the rank cost multiplier has been applied to the ladder // with information on how to change it. @@ -544,6 +637,8 @@ public void autoConfigureRanks(CommandSender sender, // Reloads autoFeatures and blockConverters: AutoFeaturesWrapper.getInstance().reloadConfigs(); + AutoFeaturesWrapper.getBlockConvertersInstance().reloadConfig(); + // Reset all player to the first rank on the default ladder: PrisonRanks.getInstance().checkAllPlayersForJoin(); @@ -587,6 +682,9 @@ public void autoConfigureRanks(CommandSender sender, } private String extractParameter( String key, String options ) { + return extractParameter( key, options, true ); + } + private String extractParameter( String key, String options, boolean tryLowerCase ) { String results = null; int idx = options.indexOf( key ); if ( idx != -1 ) { @@ -596,6 +694,10 @@ private String extractParameter( String key, String options ) { } results = options.substring( idx, idxEnd ); } + else if ( tryLowerCase ) { + // try again, but lowercase the key + results = extractParameter( key.toLowerCase(), options, false ); + } return results; } @@ -676,6 +778,8 @@ public void listRanks(CommandSender sender, else { display = new ChatDisplay( "List ALL Ranks" ); + display.addSupportHyperLinkData( "Rank List" ); + listAllRanksByLadders( display, hasPerm, rPlayer ); } @@ -836,6 +940,8 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP String rankHeader = ranksListHeaderMsg( ladder.getName() ); ChatDisplay display = new ChatDisplay( rankHeader ); + display.addSupportHyperLinkData( "Ladder List %s", ladder.getName() ); + display.addText( " " + PrisonRanks.getInstance().getLadderManager().printRankLadderInfoHeader() ); display.addText( " " + PrisonRanks.getInstance().getLadderManager().printRankLadderInfoDetail(ladder) ); @@ -859,23 +965,35 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP new BulletedListComponent.BulletedListBuilder(); DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.0000"); + DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); // Here's the deal... With color codes, Java's String.format() cannot detect the correct // length of a tag. So go through all tags, strip the colors, and see how long they are. // We need to know the max length so we can pad the others with periods to align all costs. int maxRankNameSize = 0; int maxRankTagNoColorSize = 0; + int maxRankCostSize = 0; + for (Rank rank : ladder.getRanks()) { - if ( rank.getName().length() > maxRankNameSize ) { - maxRankNameSize = rank.getName().length(); + String nameNoColor = Text.stripColor( rank.getName() ); + if ( nameNoColor.length() > maxRankNameSize ) { + maxRankNameSize = nameNoColor.length(); } String tag = rank.getTag() == null ? "" : rank.getTag(); String tagNoColor = Text.stripColor( tag ); if ( tagNoColor.length() > maxRankTagNoColorSize ) { maxRankTagNoColorSize = tagNoColor.length(); } + + int costSize = iFmt.format( rank.getRawRankCost() ).length(); + if ( costSize > maxRankCostSize ) { + maxRankCostSize = costSize; + } } + maxRankCostSize++; + String nameStringFormat = "%-" + maxRankNameSize + "s "; + String tagStringFormat = "%-" + maxRankTagNoColorSize + "s "; RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); @@ -885,12 +1003,24 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP boolean defaultRank = (LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladder.getName() ) && first); + String nameNoColor = Text.stripColor( rank.getName() ); + String tag = rank.getTag() == null ? "" : rank.getTag(); + String tagNoColor = Text.stripColor( tag ); +// String rankCost = iFmt.format( rank.getRawRankCost() ); + + String nameFormatted = String.format( nameStringFormat, nameNoColor ); + nameFormatted = nameFormatted.replace( nameNoColor, rank.getName() ); + + String tagFormatted = String.format( tagStringFormat, tagNoColor ); + tagFormatted = tagFormatted.replace( tagNoColor, tag ); + + // Since the formatting gets confused with color formatting, we must // strip the color codes and then inject them back in. So instead, this // provides the formatting rules for both name and rank tag, thus // taking in to consideration the color codes and if the hasPerms is // true. To prevent variable space issues, the difference is filled in with periods. - String textRankNameString = padRankName( rank, maxRankNameSize, maxRankTagNoColorSize, hasPerm ); +// String textRankNameString = padRankName( rank, maxRankNameSize, maxRankTagNoColorSize, hasPerm ); // // trick it to deal correctly with tags. Tags can have many colors, but // // it will render as if it had the colors stripped. So first generate the @@ -945,26 +1075,43 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP String players = rank.getPlayers().size() == 0 ? "" : " &dPlayers: &3" + rank.getPlayers().size(); - String rawRankId = ( hasPerm ? - String.format( "(rankId: %s%s%s)", - Integer.toString( rank.getId() ), - (rank.getRankPrior() == null ? "" : " -"), - (rank.getRankNext() == null ? "" : " +") ) - : ""); +// String rawRankId = ( hasPerm ? +// String.format( "(rankId: %s%s%s)", +// Integer.toString( rank.getId() ), +// (rank.getRankPrior() == null ? "" : " -"), +// (rank.getRankNext() == null ? "" : " +") ) +// : ""); + + + StringBuilder minesSb = new StringBuilder(); + for ( ModuleElement mine : rank.getMines() ) { + if ( minesSb.length() > 0 ) { + minesSb.append( "&6,&7" ); + } + minesSb.append( mine.getTag() ); + } + if ( minesSb.length() > 0 ) { + minesSb.insert( 0, " &6Mines: &7" ); +// minesSb.append( "8" ); + } String text = - String.format("&3%s &7%-17s%s&7 &b%s &3%s %s&7 %s%s", - textRankNameString, - Text.numberToDollars( rankCost ), + String.format("&3%s %s &7%" + maxRankCostSize + "s &a%s &b%s %s&7 %s%s%s", + nameFormatted, + tagFormatted, + + iFmt.format( rankCost ), +// Text.numberToDollars( rankCost ), (defaultRank ? "{def}" : ""), rankMultiplier, - rawRankId, +// rawRankId, textCurrency, textCmdCount, - players + players, + minesSb.toString() ); // // Swap the color tag back in: @@ -972,7 +1119,7 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP if ( defaultRank ) { // Swap out the default placeholder for the actual content: - text = text.replace( "{def}", "&c(&9Default&c)" ); + text = text.replace( "{def}", "&c(&r&9Default&r&c)" ); } String rankName = rank.getName(); @@ -1161,6 +1308,9 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt ChatDisplay display = new ChatDisplay( ranksInfoHeaderMsg( title )); + display.addSupportHyperLinkData( "Rank %s", rank.getName() ); + + boolean isOp = sender != null && sender.isOp(); boolean isConsole = sender == null || !sender.isPlayer(); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayers.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayers.java index be8763fd6..de0a28878 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayers.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayers.java @@ -12,6 +12,7 @@ import tech.mcprison.prison.file.FileIOData; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.tasks.TopNPlayerUpdateAsyncTask; @@ -130,7 +131,11 @@ public File getSaveFile() { */ private void launchTopNPlayerUpdateAsyncTask() { - if ( PrisonRanks.getInstance().getPlayerManager() != null ) { + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null && + PrisonRanks.getInstance().getDefaultLadder().getRanks().size() > 0 + ) { Long delayTicks = Prison.get().getPlatform().getConfigLong( "topNPlayers.refresh.delay-ticks", DELAY_THIRTY_SECONDS_TICKS ); @@ -140,6 +145,15 @@ private void launchTopNPlayerUpdateAsyncTask() { TopNPlayerUpdateAsyncTask.submitTaskTimerAsync( this, delayTicks, intervalTicks ); } + else if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getDefaultLadder().getRanks().size() == 0 ) { + + Output.get().logWarn( "TopNPlayer: Cannot start the TopNPlayer task. Ranks are " + + "enabled, but there are no default ranks setup. " + + "Either turn off the Ranks Module, or add ranks and " + + "then restart the server to get the TopNPlayer task running."); + } } @@ -169,7 +183,9 @@ private void launchTopNPlayerUpdateAsyncTask() { public void loadSaveFile() { // If Ranks module is not loaded, then do not try to load any save file: - if ( PrisonRanks.getInstance().getPlayerManager() == null ) { + if ( PrisonRanks.getInstance() == null || + !PrisonRanks.getInstance().isEnabled() || + PrisonRanks.getInstance().getPlayerManager() == null ) { // Ranks is not loaded, so reset to empties: setTopNList( new ArrayList<>() ); @@ -242,7 +258,9 @@ public void loadSaveFile() { */ public void forceReloadAllPlayers() { - if ( PrisonRanks.getInstance().getPlayerManager() != null ) { + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null ) { long start = System.nanoTime(); @@ -380,7 +398,9 @@ private void addPlayerData( TopNPlayersData topN, PlayerState activePlayerState public void refreshAndSort() { - if ( PrisonRanks.getInstance().getPlayerManager() == null ) { + if ( PrisonRanks.getInstance() == null || + !PrisonRanks.getInstance().isEnabled() || + PrisonRanks.getInstance().getPlayerManager() == null ) { return; } @@ -491,7 +511,9 @@ public void refreshAndSort() { private void calculateAllRankScores( ArrayList topNList ) { - if ( PrisonRanks.getInstance().getPlayerManager() != null ) { + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null ) { for ( TopNPlayersData topN : topNList ) { @@ -590,7 +612,9 @@ else if ( getArchivedMap().containsKey( key ) ) { */ public void updatePlayerData( RankPlayer rPlayer ) { - if ( PrisonRanks.getInstance().getPlayerManager() != null ) { + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null ) { addPlayerData( rPlayer); @@ -662,7 +686,9 @@ public RankPlayer getTopNRankArchivedPlayer( int rankPosition ) { private RankPlayer getTopNRankPlayer( int rankPosition, boolean archived ) { RankPlayer rPlayer = null; - if ( PrisonRanks.getInstance().getPlayerManager() != null ) { + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null ) { ArrayList tList = archived ? diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java index b2613746c..f9bd31eac 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java @@ -134,9 +134,13 @@ public void saveLadder(RankLadder ladder, String fileKey) throws IOException { * @throws IOException If the ladder could not be serialized, or if the ladder could not be saved to the file. */ private void saveLadder(RankLadder ladder) throws IOException { - this.saveLadder(ladder, "ladder_" + ladder.getId()); + this.saveLadder(ladder, getLadderName(ladder)); } + private String getLadderName( RankLadder ladder ) { + return "ladder_" + ladder.getId(); + } + /** *

This is the save function that should be used from outside of the LadderManager, such as * within the LadderCommands functions because this will be able to handle the possible @@ -369,5 +373,17 @@ public String printRankLadderInfoDetail( RankLadder ladder ) { return ladderInfo; } + + public String getLadderByFileName(String fileName) { + String results = ""; + + for (RankLadder rankLadder : loadedLadders) { + String ladderFileName = getLadderName(rankLadder) + ".json"; + if ( ladderFileName.equalsIgnoreCase(fileName) ) { + results = rankLadder.getName(); + } + } + return results; + } } 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 f56f41209..c4d6d20d8 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 @@ -37,6 +37,7 @@ import tech.mcprison.prison.placeholders.PlaceholderAttributeBar; import tech.mcprison.prison.placeholders.PlaceholderAttributeNumberFormat; import tech.mcprison.prison.placeholders.PlaceholderAttributeText; +import tech.mcprison.prison.placeholders.PlaceholderAttributeTime; import tech.mcprison.prison.placeholders.PlaceholderIdentifier; import tech.mcprison.prison.placeholders.PlaceholderManager; import tech.mcprison.prison.placeholders.PlaceholderManager.PlaceholderFlags; @@ -718,6 +719,7 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); PlaceholderAttributeText attributeText = identifier.getAttributeText(); + PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); int sequence = identifier.getSequence(); @@ -1570,6 +1572,19 @@ public void reloadPlaceholders() { getTranslatedPlaceHolderKeys(); } + + + public String getRankByFileName(String fileName) { + String results = ""; + + for (Rank rank : loadedRanks) { + String rankFileName = rank.filename() + ".json"; + if ( rankFileName.equalsIgnoreCase(fileName) ) { + results = rank.getName(); + } + } + return results; + } private List getLoadedRanks() { return loadedRanks; diff --git a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/messages/SpigotVariousGuiMessages.java b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/messages/SpigotVariousGuiMessages.java index 479589162..0c254e71f 100644 --- a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/messages/SpigotVariousGuiMessages.java +++ b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/messages/SpigotVariousGuiMessages.java @@ -53,7 +53,7 @@ protected String prisonSellallTest03Msg() { } - protected String sellallAmountEarnedMsg( String earningsAmount ) { + public String sellallAmountEarnedMsg( String earningsAmount ) { return PrisonSellall.getInstance().getSellallMessages() .getLocalizable( "sellall_spigot_utils__money_earned" ) diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 3ab4ae5fe..1e33b8b42 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -94,6 +94,8 @@ dependencies { implementation project(':prison-ranks') implementation project(':prison-sellall') + // implementation project(':prison-worldguard6') + // https://mvnrepository.com/artifact/org.bstats/bstats-base // https://mvnrepository.com/artifact/org.bstats/bstats-bukkit @@ -112,6 +114,28 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' + +/* + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-core + implementation 'com.sk89q.worldedit:worldedit-core:7.2.15' + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-bukkit + compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.15' + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-core + compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-bukkit + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard.worldguard-libs/core + implementation 'com.sk89q.worldguard.worldguard-libs:core:7.0.8' +*/ + + + + compileOnly 'me.clip:placeholderapi:2.11.2' //compileOnly 'me.clip:placeholderapi:2.10.9' @@ -168,7 +192,7 @@ dependencies { // https://github.com/tr7zw/Item-NBT-API/wiki/Using-Gradle // https://www.spigotmc.org/resources/nbt-api.7939/ // https://mvnrepository.com/artifact/de.tr7zw/item-nbt-api-plugin - implementation 'de.tr7zw:item-nbt-api:2.11.3' + implementation 'de.tr7zw:item-nbt-api:2.12.0' // implementation 'de.tr7zw:item-nbt-api-plugin:2.11.2' // implementation 'de.tr7zw:item-nbt-api-plugin:2.10.0' // implementation 'de.tr7zw:item-nbt-api-plugin:2.9.2' diff --git a/prison-spigot/lib/CoinsEngine pseudo API not-real.jar b/prison-spigot/lib/CoinsEngine pseudo API not-real.jar new file mode 100644 index 000000000..31eebc6c2 Binary files /dev/null and b/prison-spigot/lib/CoinsEngine pseudo API not-real.jar differ diff --git a/prison-spigot/lib/XPrison-api-1.12.13-RELEASE.jar b/prison-spigot/lib/XPrison-api-1.12.13-RELEASE.jar new file mode 100644 index 000000000..6ae3be4da Binary files /dev/null and b/prison-spigot/lib/XPrison-api-1.12.13-RELEASE.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 c560ec3a9..3bfc67237 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 @@ -42,6 +42,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.SimpleCommandMap; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.event.EventPriority; import org.bukkit.event.player.AsyncPlayerChatEvent; @@ -97,6 +98,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.RowComponent; import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.commands.LadderCommands; import tech.mcprison.prison.ranks.commands.RanksCommands; import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; @@ -113,6 +115,9 @@ import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsExplosiveEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsJackHammerEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerTokenEnchant; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonExplosionTriggerEvent; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonLayerTriggerEvent; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonNukeTriggerEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerZenchantments; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -407,11 +412,13 @@ else if ( oPlayer == null || oPlayer.getName() == null ) { return plugin.getDescription().getVersion(); } - @Override public File getPluginDirectory() { + @Override + public File getPluginDirectory() { return plugin.getDataFolder(); } - @Override public void registerCommand(PluginCommand command) { + @Override + public void registerCommand(PluginCommand command) { try { Command cmd = new Command( command.getLabel(), @@ -555,15 +562,18 @@ public PluginCommand findCommand( String label ) { return results; } - @Override public List getCommands() { + @Override + public List getCommands() { return commands; } - @Override public void dispatchCommand(String cmd) { + @Override + public void dispatchCommand(String cmd) { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), cmd); } - @Override public void dispatchCommand(tech.mcprison.prison.internal.CommandSender sender, String cmd) { + @Override + public void dispatchCommand(tech.mcprison.prison.internal.CommandSender sender, String cmd) { if ( sender instanceof SpigotCommandSender ) { SpigotCommandSender cmdSender = (SpigotCommandSender) sender; @@ -580,7 +590,8 @@ public PluginCommand findCommand( String label ) { } - @Override public Scheduler getScheduler() { + @Override + public Scheduler getScheduler() { return plugin.scheduler; } @@ -927,9 +938,11 @@ public String getConfigString( String key, String defaultValue ) { } + @SuppressWarnings("unchecked") @Override - public List getConfigStringArray( String key ) { - return SpigotPrison.getInstance().getConfig().getList( key, new ArrayList() ); + public List getConfigStringArray( String key ) { + return (List) SpigotPrison.getInstance().getConfig() + .getList( key, new ArrayList() ); } @@ -1062,6 +1075,26 @@ public double getConfigDouble( String key, double defaultValue ) { return results; } + /** + *

Given the path to a hash, this will return all of the keys within + * the hash at the root level. It will not traverse deeper. + * The list of keys can then be used to access all of the values. + *

+ * + */ + @Override + public List getConfigHashKeys( String hashPrefix ) { + List keys = new ArrayList<>(); + + ConfigurationSection configSection = + SpigotPrison.getInstance().getConfig().getConfigurationSection( hashPrefix ); + + if ( configSection != null ) { + keys.addAll( configSection.getKeys(false) ); + } + + return keys; + } @Override public boolean isWorldExcluded( String worldName ) { @@ -1990,6 +2023,20 @@ public List buildBlockListXMaterial() { blockList.add( new SellAllBlockData( XMaterial.SUGAR, 13 ) ); blockList.add( new SellAllBlockData( XMaterial.PAPER, 13 ) ); + + blockList.add( new SellAllBlockData( XMaterial.SOUL_SAND, 25 ) ); + blockList.add( new SellAllBlockData( XMaterial.BROWN_MUSHROOM, 5 ) ); + blockList.add( new SellAllBlockData( XMaterial.BROWN_MUSHROOM_BLOCK, 5 ) ); + blockList.add( new SellAllBlockData( XMaterial.RED_MUSHROOM, 5 ) ); + blockList.add( new SellAllBlockData( XMaterial.RED_MUSHROOM_BLOCK, 5 ) ); + blockList.add( new SellAllBlockData( XMaterial.SLIME_BALL, 7 ) ); + blockList.add( new SellAllBlockData( XMaterial.SLIME_BLOCK, 63 ) ); + blockList.add( new SellAllBlockData( XMaterial.PACKED_ICE, 7 ) ); + + blockList.add( new SellAllBlockData( XMaterial.BRICK, 4 ) ); + blockList.add( new SellAllBlockData( XMaterial.BRICKS, 16 ) ); // 1 bricks = 4 brick + + return blockList; } @@ -2085,6 +2132,9 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { results.add( " " ); } + else { + results.add( "&7Ranks: &9Not Enabled." ); + } } @@ -2118,16 +2168,30 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { results.add( mineDetails ); } + else { + results.add( "&7Mines: &9Not Enabled." ); + } // Load the autoFeaturesConfig.yml and blockConvertersConfig.json files: AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); - afw.reloadConfigs(); +// afw.reloadConfigs(); + +// AutoFeaturesWrapper.getBlockConvertersInstance(); + + + boolean isAutoManagerEnabled = afw.isBoolean( AutoFeatures.isAutoManagerEnabled ); - results.add( String.format("AutoManager Enabled:&b %s", isAutoManagerEnabled) ); + + String autoMangerHeader = "&7AutoManager: " + + ( isAutoManagerEnabled ? + "&9Enabled" : + "&9Not Enabled" ); + + results.add( autoMangerHeader ); if ( isAutoManagerEnabled ) { @@ -2148,78 +2212,98 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { Boolean.toString( bbeCabebd ) ) ); + + results.add( formatAFEvent( "'&7org.bukkit.BlockBreakEvent&3'", AutoFeatures.blockBreakEventPriority ) ); + results.add( formatAFEvent( "Prison's own '&7ExplosiveBlockBreakEvent&3'", AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); + results.add( formatAFEvent( "Pulsi_'s PrisonEnchants '&7PEExplosiveEvent&3'", AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); + results.add( formatAFEvent( "TokenEnchant '&7BlockExplodeEvent&3'", AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); + + results.add( formatAFEvent( "CrazyEnchant '&7BlastUseEvent&3'", AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); + results.add( formatAFEvent( "RevEnchant '&7ExplosiveEvent&3'", AutoFeatures.RevEnchantsExplosiveEventPriority ) ); + results.add( formatAFEvent( "RevEnchant '&7JackHammerEvent&3'", AutoFeatures.RevEnchantsJackHammerEventPriority ) ); + results.add( formatAFEvent( "Zenchantments '&7BlockShredEvent&3'", AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); + + results.add( formatAFEvent( "XPrison '&7ExplosionTriggerEvent&3'", AutoFeatures.XPrisonExplosionTriggerEventPriority ) ); + results.add( formatAFEvent( "XPrison '&7LayerTriggerEvent&3'", AutoFeatures.XPrisonLayerTriggerEventPriority ) ); + results.add( formatAFEvent( "XPrison '&7NukeTriggerEvent&3'", AutoFeatures.XPrisonNukeTriggerEventPriority ) ); + + - - String bbePriority = afw.getMessage( AutoFeatures.blockBreakEventPriority ); - BlockBreakPriority blockBreakPriority = BlockBreakPriority.fromString( bbePriority ); - results.add( String.format(". '&7org.bukkit.BlockBreakEvent&3' Priority:&b %s", - blockBreakPriority.name() ) ); - - String pebbePriority = afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); - boolean isPebbeEnabled = pebbePriority != null && !"DISABLED".equalsIgnoreCase( pebbePriority ); - BlockBreakPriority pebbeEventPriority = BlockBreakPriority.fromString( pebbePriority ); - results.add( String.format("%s. Prison's own '&7ExplosiveBlockBreakEvent&3' Priority:&b %s %s", - (isPebbeEnabled ? "" : "+" ), - pebbeEventPriority.name(), - (isPebbeEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String bbePriority = afw.getMessage( AutoFeatures.blockBreakEventPriority ); +// BlockBreakPriority blockBreakPriority = BlockBreakPriority.fromString( bbePriority ); +// results.add( String.format(". '&7org.bukkit.BlockBreakEvent&3' Priority:&b %s", +// blockBreakPriority.name() ) ); - String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); - boolean isPeeeEnabled = peeePriority != null && !"DISABLED".equalsIgnoreCase( peeePriority ); - BlockBreakPriority peeeEventPriority = BlockBreakPriority.fromString( peeePriority ); - results.add( String.format("%s. Pulsi_'s PrisonEnchants '&7PEExplosiveEvent&3' Priority:&b %s %s", - (isPeeeEnabled ? "" : "+" ), - peeeEventPriority.name(), - (isPeeeEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String pebbePriority = afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); +// boolean isPebbeEnabled = pebbePriority != null && !"DISABLED".equalsIgnoreCase( pebbePriority ); +// BlockBreakPriority pebbeEventPriority = BlockBreakPriority.fromString( pebbePriority ); +// results.add( String.format("%s. Prison's own '&7ExplosiveBlockBreakEvent&3' Priority:&b %s %s", +// (isPebbeEnabled ? "" : "+" ), +// pebbeEventPriority.name(), +// (isPebbeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); - String tebePriority = afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); - boolean isTebeEnabled = tebePriority != null && !"DISABLED".equalsIgnoreCase( tebePriority ); - BlockBreakPriority tebEventPriority = BlockBreakPriority.fromString( tebePriority ); - results.add( String.format("%s. TokenEnchant '&7BlockExplodeEvent&3' Priority:&b %s %s", - (isTebeEnabled ? "" : "+" ), - tebEventPriority.name(), - (isTebeEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); +// boolean isPeeeEnabled = peeePriority != null && !"DISABLED".equalsIgnoreCase( peeePriority ); +// BlockBreakPriority peeeEventPriority = BlockBreakPriority.fromString( peeePriority ); +// results.add( String.format("%s. Pulsi_'s PrisonEnchants '&7PEExplosiveEvent&3' Priority:&b %s %s", +// (isPeeeEnabled ? "" : "+" ), +// peeeEventPriority.name(), +// (isPeeeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); +// +// String tebePriority = afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); +// boolean isTebeEnabled = tebePriority != null && !"DISABLED".equalsIgnoreCase( tebePriority ); +// BlockBreakPriority tebEventPriority = BlockBreakPriority.fromString( tebePriority ); +// results.add( String.format("%s. TokenEnchant '&7BlockExplodeEvent&3' Priority:&b %s %s", +// (isTebeEnabled ? "" : "+" ), +// tebEventPriority.name(), +// (isTebeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); - String reeePriority = afw.getMessage( AutoFeatures.RevEnchantsExplosiveEventPriority ); - boolean isReeeEnabled = reeePriority != null && !"DISABLED".equalsIgnoreCase( reeePriority ); - BlockBreakPriority reeEventPriority = BlockBreakPriority.fromString( reeePriority ); - results.add( String.format("%s. RevEnchant '&7ExplosiveEvent&3' Priority:&b %s %s", - (isReeeEnabled ? "" : "+" ), - reeEventPriority.name(), - (isReeeEnabled ? "&2Enabled" : "&cDisabled") - ) ); - String rejhePriority = afw.getMessage( AutoFeatures.RevEnchantsJackHammerEventPriority ); - boolean isRejheEnabled = rejhePriority != null && !"DISABLED".equalsIgnoreCase( rejhePriority ); - BlockBreakPriority rejhEventPriority = BlockBreakPriority.fromString( rejhePriority ); - results.add( String.format("%s. RevEnchant '&7JackHammerEvent&3' Priority:&b %s %s", - (isRejheEnabled ? "" : "+" ), - rejhEventPriority.name(), - (isRejheEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String reeePriority = afw.getMessage( AutoFeatures.RevEnchantsExplosiveEventPriority ); +// boolean isReeeEnabled = reeePriority != null && !"DISABLED".equalsIgnoreCase( reeePriority ); +// BlockBreakPriority reeEventPriority = BlockBreakPriority.fromString( reeePriority ); +// results.add( String.format("%s. RevEnchant '&7ExplosiveEvent&3' Priority:&b %s %s", +// (isReeeEnabled ? "" : "+" ), +// reeEventPriority.name(), +// (isReeeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); +// +// String rejhePriority = afw.getMessage( AutoFeatures.RevEnchantsJackHammerEventPriority ); +// boolean isRejheEnabled = rejhePriority != null && !"DISABLED".equalsIgnoreCase( rejhePriority ); +// BlockBreakPriority rejhEventPriority = BlockBreakPriority.fromString( rejhePriority ); +// results.add( String.format("%s. RevEnchant '&7JackHammerEvent&3' Priority:&b %s %s", +// (isRejheEnabled ? "" : "+" ), +// rejhEventPriority.name(), +// (isRejheEnabled ? "&2Enabled" : "&cDisabled") +// ) ); - String cebuePriority = afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); - boolean isCebueEnabled = cebuePriority != null && !"DISABLED".equalsIgnoreCase( cebuePriority ); - BlockBreakPriority cebuEventPriority = BlockBreakPriority.fromString( cebuePriority ); - results.add( String.format("%s. CrazyEnchant '&7BlastUseEvent&3' Priority:&b %s %s", - (isCebueEnabled ? "" : "+" ), - cebuEventPriority.name(), - (isCebueEnabled ? "&2Enabled" : "&cDisabled") - ) ); - - String zbsePriority = afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); - boolean isZbseEnabled = zbsePriority != null && !"DISABLED".equalsIgnoreCase( zbsePriority ); - BlockBreakPriority zbsEventPriority = BlockBreakPriority.fromString( zbsePriority ); - results.add( String.format("%s. Zenchantments '&7BlockShredEvent&3' Priority:&b %s %s", - (isZbseEnabled ? "" : "+" ), - zbsEventPriority.name(), - (isZbseEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String cebuePriority = afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); +// boolean isCebueEnabled = cebuePriority != null && !"DISABLED".equalsIgnoreCase( cebuePriority ); +// BlockBreakPriority cebuEventPriority = BlockBreakPriority.fromString( cebuePriority ); +// results.add( String.format("%s. CrazyEnchant '&7BlastUseEvent&3' Priority:&b %s %s", +// (isCebueEnabled ? "" : "+" ), +// cebuEventPriority.name(), +// (isCebueEnabled ? "&2Enabled" : "&cDisabled") +// ) ); +// +// String zbsePriority = afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); +// boolean isZbseEnabled = zbsePriority != null && !"DISABLED".equalsIgnoreCase( zbsePriority ); +// BlockBreakPriority zbsEventPriority = BlockBreakPriority.fromString( zbsePriority ); +// results.add( String.format("%s. Zenchantments '&7BlockShredEvent&3' Priority:&b %s %s", +// (isZbseEnabled ? "" : "+" ), +// zbsEventPriority.name(), +// (isZbseEnabled ? "&2Enabled" : "&cDisabled") +// ) ); + + + + // String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); // boolean isPeeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); // BlockBreakPriority peeEventPriority = BlockBreakPriority.fromString( peeePriority ); @@ -2271,13 +2355,34 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { (isDurabilityEnabled ? "" : "+"), isDurabilityEnabled) ); + boolean isPreventToolBreakage = afw.isBoolean( AutoFeatures.isPreventToolBreakage ); + results.add( String.format("%s. Prevent Tool Breakage:&b %s", + (isPreventToolBreakage ? "" : "+"), + isPreventToolBreakage) ); + + results.add( String.format("%s. Prevent Tool Breakage Threshold:&b %s", + (isPreventToolBreakage ? "" : "+"), + afw.getInteger( AutoFeatures.preventToolBreakageThreshold )) ); + + + + boolean isCalcFortune = afw.isBoolean( AutoFeatures.isCalculateFortuneEnabled ); + results.add( String.format(". Calculate Fortune:&b %s", isCalcFortune) ); - results.add( String.format("+. . Fortune Multiplier:&b %s", + + boolean isUseTEFortuneLevel = afw.isBoolean( AutoFeatures.isUseTokenEnchantsFortuneLevel ); + results.add( String.format("%s. . Use TokenEnchants Fortune Level:&b %b", + (isUseTEFortuneLevel ? "" : "+"), + isUseTEFortuneLevel) ); + + results.add( String.format("+. . Fortune Multiplier Global:&b %s", afw.getInteger( AutoFeatures.fortuneMultiplierGlobal )) ); results.add( String.format("+. . Max Fortune Level:&b %s &3(0 = no max Level)", afw.getInteger( AutoFeatures.fortuneMultiplierMax )) ); + results.add( String.format("+. . Fortune Bukkit Drops Multiplier:&b %s &3", + afw.getDouble( AutoFeatures.fortuneBukkitDropsMultiplier )) ); boolean isExtendedBukkitFortune = afw.isBoolean( AutoFeatures.isExtendBukkitFortuneCalculationsEnabled ); results.add( String.format(". . Extended Bukkit Fortune Enabled:&b %s", @@ -2289,17 +2394,46 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { afw.getInteger( AutoFeatures.extendBukkitFortuneFactorPercentRangeHigh )) ); + boolean isAltFortune = afw.isBoolean( AutoFeatures.isCalculateAltFortuneEnabled); results.add( "+&3NOTE: If you enable Extended Bukkit Fortune, then it auto disables the following Alt Fortune Cals." ); results.add( "+&3NOTE: First try Extended Bukkit Fortune and if it does not work, then disable it and use " + "Alt Fortune." ); - results.add( String.format("%s. . Calculate Alt Fortune Enabled:&b %s %s", + results.add( String.format("%s. . Calculate Alt Fortune Enabled:&b %s", (isExtendedBukkitFortune ? "+" : "" ), - ( afw.isBoolean( AutoFeatures.isCalculateAltFortuneEnabled) ? "&2Enabled" : "&cDisabled"), - ( isExtendedBukkitFortune ? "&d[disabled by Exended Bukkit Fortune]" : "")) ); - results.add( String.format("%s. . Calculate Alt Fortune on all Blocks:&b %s %s", + ( isAltFortune ? "&2Enabled" : "&cDisabled") + ) ); + results.add( String.format("%s. . Calculate Alt Fortune on all Blocks:&b %s", (isExtendedBukkitFortune ? "+" : "" ), - ( afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled) ? "&2Enabled" : "&cDisabled"), - ( isExtendedBukkitFortune ? "&d[disabled by Exended Bukkit Fortune]" : "")) ); + ( afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled) ? "&2Enabled" : "&cDisabled") + ) ); + if ( isAltFortune && isExtendedBukkitFortune ) { + results.add( "&dWarning: Alt Fortune is disabled by Exended Bukkit Fortune." ); + } + + + boolean isGradientFortune = afw.isBoolean( AutoFeatures.isPercentGradientFortuneEnabled ); + + results.add( String.format("%s. Percent Gradient Fortune Enabled:&b %s", + (isGradientFortune ? "" : "+"), + isGradientFortune ) ); + + if ( isGradientFortune ) { + + if ( isExtendedBukkitFortune ) { + results.add( "&dWarning: Percent Gradient Fortune is disabled by Exended Bukkit Fortune." ); + } + if ( isAltFortune ) { + results.add( "&dWarning: Percent Gradient Fortune is disabled by Alt Fortune." ); + } + + results.add( String.format(". . Percent Gradient Fortune: Max Fortune Level:&b %s", + afw.getInteger( AutoFeatures.percentGradientFortuneMaxFortuneLevel )) ); + results.add( String.format(". . Percent Gradient Fortune: Max Bonus Blocks: &b %s", + afw.getInteger( AutoFeatures.percentGradientFortuneMaxBonusBlocks )) ); + results.add( String.format(". . Percent Gradient Fortune: Min Percent Randomness: &b%s", + afw.getDouble( AutoFeatures.percentGradientFortuneMinPercentRandomness )) ); + + } results.add( " " ); @@ -2365,6 +2499,25 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { } + private String formatAFEvent(String description, AutoFeatures autoFeature ) { + String results = null; + + String ePriority = AutoFeaturesWrapper.getInstance().getMessage( autoFeature ); + + BlockBreakPriority eventPriority = BlockBreakPriority.fromString( ePriority ); + + boolean isEnabled = eventPriority != BlockBreakPriority.DISABLED; + + results = String.format("%s. %s Priority:&b %s %s", + (isEnabled ? "" : "+" ), + description, + eventPriority.name(), + (isEnabled ? "&2Enabled" : "&cDisabled") + ); + + return results; + } + @Override public void prisonVersionFeatures( ChatDisplay display, boolean isBasic, boolean showLaddersAndRanks ) { @@ -2549,7 +2702,9 @@ else if ( !isBasic ) { } - + // REMOVE! The following will "load" the WorldGuard settings and then dump them as json to console + // to confirm they were loaded properly. Remove when done with this test1 +// new WorldGuardSettings(); } @@ -2620,6 +2775,20 @@ public String dumpEventListenersBlockBreakEvents() { zenchantments.dumpEventListeners( sb ); + + AutoManagerXPrisonExplosionTriggerEvent xpExplosion = new AutoManagerXPrisonExplosionTriggerEvent(); + xpExplosion.dumpEventListeners( sb ); + + AutoManagerXPrisonLayerTriggerEvent xpLayer = new AutoManagerXPrisonLayerTriggerEvent(); + xpLayer.dumpEventListeners( sb ); + + AutoManagerXPrisonNukeTriggerEvent xpNuke = new AutoManagerXPrisonNukeTriggerEvent(); + xpNuke.dumpEventListeners( sb ); + + + + + // Shorten the prison package names: // 'tmps.' = 'tech.mcprison.prison.spigot.' // 'tmpsae.' = 'tmps.autofeatures.events.' @@ -2832,45 +3001,86 @@ public void saveResource( String fileName, boolean replace ) { SpigotPrison.getInstance().saveResource( fileName, replace ); } - @Override - public String getMinesListString() { + public boolean isMineNameValid( String mineName ) { + boolean results = false; + if ( PrisonMines.getInstance().isEnabled() ) { + + Mine mine = PrisonMines.getInstance().getMine(mineName); + + results = mine != null; + } - MinesCommands mc = PrisonMines.getInstance().getMinesCommands(); + return results; + } + + @Override + public String getMinesListString() { + String results = ""; - - ChatDisplay display = new ChatDisplay("Mines"); - mc.getMinesList( display, MineManager.MineSortOrder.sortOrder, "all", null ); - - StringBuilder sb = display.toStringBuilder(); - - sb.append( "\n" ); - - mc.allMinesInfoDetails( sb ); + if ( PrisonMines.getInstance().isEnabled() ) { + + MinesCommands mc = PrisonMines.getInstance().getMinesCommands(); + + + ChatDisplay display = new ChatDisplay("Mines"); + + display.addSupportHyperLinkData( "Mines List" ); + + // get the mine list: + mc.getMinesList( display, MineManager.MineSortOrder.sortOrder, "all", null ); + + StringBuilder sb = display.toStringBuilder(); + + sb.append( "\n" ); + + // get the mine details for all mines: + mc.allMinesInfoDetails( sb ); + + results = sb.toString(); + } - return sb.toString(); + return results; // return Text.stripColor( sb.toString() ); } @Override public String getRanksListString() { + StringBuilder sb = new StringBuilder(); - RanksCommands rc = + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + + LadderCommands lc = + PrisonRanks.getInstance().getRankManager().getLadderCommands(); + + RanksCommands rc = PrisonRanks.getInstance().getRankManager().getRanksCommands(); - - - ChatDisplay display = new ChatDisplay("Ranks"); - - RankPlayer rPlayer = null; - rc.listAllRanksByLadders( display, true, rPlayer ); - - StringBuilder sb = display.toStringBuilder(); - - sb.append( "\n" ); - - rc.listAllRanksByInfo( sb ); + + sb.append( "\n\n" ); + + ChatDisplay displayLadders = lc.getLadderList(); + + sb.append( displayLadders.toStringBuilder() ); + sb.append( "\n" ); + + + RankPlayer rPlayer = null; + + ChatDisplay displayRanks = new ChatDisplay("Ranks"); + rc.listAllRanksByLadders( displayRanks, true, rPlayer ); + + sb.append( displayRanks.toStringBuilder() ); + sb.append( "\n" ); + + + rc.listAllRanksByInfo( sb ); // rc.allRanksInfoDetails( sb ); + } + else { + sb.append( "Ranks are disabled.\n\n" ); + } + return sb.toString(); // return Text.stripColor( sb.toString() ); @@ -3115,4 +3325,27 @@ public int getMinY() { public int getMaxY() { return SpigotCompatibility.getInstance().getMaxY(); } + + @Override + public String getLadderByFileName(String name) { + String results = ""; + + if ( PrisonRanks.getInstance().isEnabled() ) { + results = PrisonRanks.getInstance().getLadderManager().getLadderByFileName( name ); + } + + return results; + } + + @Override + public String getRankByFileName(String name) { + String results = ""; + + if ( PrisonRanks.getInstance().isEnabled() ) { + + results = PrisonRanks.getInstance().getRankManager().getRankByFileName( name ); + } + + return results; + } } 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 4008430ef..1945db12c 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.PrisonCommand.RegisteredPluginsData; import tech.mcprison.prison.alerts.Alerts; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.backups.PrisonBackups; import tech.mcprison.prison.integration.Integration; import tech.mcprison.prison.integration.IntegrationType; @@ -66,7 +67,9 @@ import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener; import tech.mcprison.prison.spigot.bstats.PrisonBStats; import tech.mcprison.prison.spigot.commands.PrisonSpigotBackpackCommands; +import tech.mcprison.prison.spigot.commands.PrisonSpigotGUIBackPackCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotGUICommands; +import tech.mcprison.prison.spigot.commands.PrisonSpigotGUISellAllCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotMinesCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotPrestigeCommands; import tech.mcprison.prison.spigot.commands.PrisonSpigotRanksCommands; @@ -78,6 +81,7 @@ 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.CoinsEngineEconomy; import tech.mcprison.prison.spigot.economies.EssentialsEconomy; import tech.mcprison.prison.spigot.economies.GemsEconomy; import tech.mcprison.prison.spigot.economies.SaneEconomy; @@ -311,7 +315,10 @@ public void onEnableStartup() { Bukkit.getPluginManager().registerEvents(new ListenersPrisonManager(),this); - if ( getConfig().getBoolean( "slime-fun" ) ) { + boolean slimeFunEnabled1 = SpigotPrison.getInstance().getConfig().getBoolean("slime-fun"); + boolean slimeFunEnabled2 = SpigotPrison.getInstance().getConfig().getBoolean("slime-fun.enabled"); + + if ( slimeFunEnabled1 || slimeFunEnabled2 ) { Bukkit.getPluginManager().registerEvents(new SlimeBlockFunEventListener(), this); } @@ -330,6 +337,14 @@ public void onEnableStartup() { // Sellall set to disabled since it will be set to the correct value in enableModulesAndCommands(): isSellAllEnabled = false; + + + // Load the autoFeaturesConfig.yml and blockConvertersConfig.json files: + AutoFeaturesWrapper.getInstance(); + AutoFeaturesWrapper.getBlockConvertersInstance(); + + + // This is the loader for modules and commands: enableModulesAndCommands(); @@ -346,6 +361,7 @@ public void onEnableStartup() { // The BlockBreakEvents must be registered after the mines and ranks modules have been enabled: + // Auto features will prevent this if it's disabled. getBlockBreakEventListeners().registerAllBlockBreakEvents( this ); @@ -403,9 +419,9 @@ public void onEnableStartup() { - // Setup mine bombs: + // Setup mine bombs and validate to spigot version: PrisonUtilsMineBombs.getInstance().reloadPrisonMineBombs(); - + PrisonUtilsMineBombs.getInstance().validateMineBombsSpigotVersion(); // Enable Temp spigot commands: new SpigotCommand(); @@ -928,6 +944,7 @@ private void initIntegrations() { registerIntegration(new EssentialsEconomy()); registerIntegration(new SaneEconomy()); registerIntegration(new GemsEconomy()); + registerIntegration(new CoinsEngineEconomy()); registerIntegration(new VaultPermissions()); registerIntegration(new LuckPerms5()); @@ -1031,14 +1048,18 @@ private void initModulesAndCommands() { YamlConfiguration modulesConf = loadConfig("modules.yml"); + boolean isMinesEnabled = false; boolean isRanksEnabled = false; // TODO: This business logic needs to be moved to the Module Manager: if (modulesConf.getBoolean("mines")) { + isMinesEnabled = true; + Prison.get().getModuleManager() .registerModule(new PrisonMines(getDescription().getVersion())); - Prison.get().getCommandHandler().registerCommands( new PrisonSpigotMinesCommands() ); + // The GUI handler for mines... cannot be hooked up here: +// Prison.get().getCommandHandler().registerCommands( new PrisonSpigotMinesCommands() ); } else { Output.get().logInfo("&7Modules: &cPrison Mines are disabled and were not Loaded. "); @@ -1116,13 +1137,14 @@ private void initModulesAndCommands() { // Do not enable sellall if ranks is not loaded since it uses player ranks: if ( isRanksEnabled ) { - Prison.get().getCommandHandler().registerCommands( new PrisonSpigotRanksCommands() ); + // enable under GUI: +// Prison.get().getCommandHandler().registerCommands( new PrisonSpigotRanksCommands() ); - // NOTE: If ranks module is enabled, then try to register prestiges commands if enabled: - 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() ); - } +// // NOTE: If ranks module is enabled, then try to register prestiges commands if enabled: +// 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() ); +// } } @@ -1133,11 +1155,46 @@ private void initModulesAndCommands() { } - // This registers the admin's /gui commands - // GUI commands were updated to prevent use of ranks commands when ranks module is not loaded. - if (getConfig().getString("prison-gui-enabled").equalsIgnoreCase("true")) { + // The following will enable all of the GUI related commands. It's important that they + // cannot be enabled elsewhere, or at least the 'prison-gui-enabled' must control + // their registration: + if ( Prison.get().getPlatform().getConfigBooleanFalse( "prison-gui-enabled" ) ) { + + // Prison's primary GUI commands: Prison.get().getCommandHandler().registerCommands( new PrisonSpigotGUICommands() ); + + + if ( isMinesEnabled ) { + // The GUI handler for mines... cannot be hooked up here: + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotMinesCommands() ); + } + + + if ( isRanksEnabled ) { + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotRanksCommands() ); + + // NOTE: If ranks module is enabled, then try to register prestiges commands if enabled: + 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() ); + } + } + + + if ( isBackPacksEnabled ) { + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotGUIBackPackCommands() ); + } + + + if ( isSellAllEnabled ) { + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotGUISellAllCommands() ); + } } + +// // This registers the admin's /gui commands +// // GUI commands were updated to prevent use of ranks commands when ranks module is not loaded. +// if (getConfig().getString("prison-gui-enabled").equalsIgnoreCase("true")) { +// } // Register prison utility commands: 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 f290b4cc4..eb992ebd6 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 @@ -65,7 +65,9 @@ public void dispatchCommand(Player player, String command) { if ( player != null && player instanceof SpigotPlayer ) { SpigotPlayer sPlayer = (SpigotPlayer) player; - Bukkit.dispatchCommand( sPlayer.getWrapper(), command ); + sPlayer.dispatchCommand( command ); + +// Bukkit.dispatchCommand( sPlayer.getWrapper(), command ); } } @@ -80,7 +82,9 @@ public void performCommand(Player player, String command) { SpigotPlayer sPlayer = (SpigotPlayer) p; - sPlayer.getWrapper().performCommand( command ); + sPlayer.dispatchCommand( command ); + +// sPlayer.getWrapper().performCommand( command ); } } } 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 e8fe0f841..c37f9f0c3 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 @@ -99,7 +99,9 @@ public static XMaterial getXMaterial( String materialName ) { public static XMaterial getXMaterial( PrisonBlock prisonBlock ) { - XMaterial xMat = getXMaterial( prisonBlock.getBlockName()); + XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial(prisonBlock); + +// XMaterial xMat = getXMaterial( prisonBlock.getBlockName()); return xMat; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index f0e4535e2..d20bf0304 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.api; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.TreeMap; @@ -9,16 +10,21 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.block.BlockBreakEvent; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.BlockBreakPriority; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.block.OnBlockBreakMines.MinesEventResults; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; +import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; /** *

This is an event that prison calls before processing the blocks that @@ -100,6 +106,12 @@ public class PrisonMinesBlockBreakEvent private boolean forceAutoSell = false; + // If forceBlockRemoval is true, then it will remove the block even if the block + // break priority is MONITOR. This setting is only used (so far) with the + // BlockConverters Event Triggers to bypass prison processing, but will allow prison + // to remove the block and then treat it like a MONITOR event so it gets counted. + private boolean forceBlockRemoval = false; + private BlockBreakPriority bbPriority; @@ -129,8 +141,9 @@ public class PrisonMinesBlockBreakEvent private StringBuilder debugInfo; - + private boolean forceDebugLogging; + public PrisonMinesBlockBreakEvent( MinesEventResults eventResults, // Block theBlock, Player player, @@ -175,7 +188,11 @@ public PrisonMinesBlockBreakEvent( this.bukkitDrops = new ArrayList<>(); - this.debugInfo = debugInfo; + this.debugInfo = new StringBuilder(); + setDebugColorCodeDebug(); + this.debugInfo.append( debugInfo ); + + this.forceDebugLogging = false; } @@ -285,6 +302,71 @@ public TreeMap getTargetBlockCounts() { return results; } + + + /** + *

This will perform a Prison's sellall on a player's inventory. + * This tracks how many nanoseconds it took to run and will log this + * information if Prison is in debug mode. This info will be appended + * to the debug info for the block break handling. + *

+ * + * @param description + */ + public void performSellAllOnPlayerInventoryLogged( String description ) { + + debugInfo.append( performSellAllOnPlayerInventoryString(description) ); + +// final long nanoStart = System.nanoTime(); +// boolean success = SellAllUtil.get().sellAllSell( getPlayer(), +// false, false, false, true, true, false); +// final long nanoStop = System.nanoTime(); +// double milliTime = (nanoStop - nanoStart) / 1000000d; +// +// DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); +// debugInfo.append( "(" ) +// .append( description) +// .append( ": " + (success ? "success" : "failed")) +// .append( " ms: " + dFmt.format( milliTime ) + ") "); + + PlayerAutoRankupTask.autoSubmitPlayerRankupTask( getSpigotPlayer(), debugInfo ); + + } + public String performSellAllOnPlayerInventoryString( String description ) { + StringBuilder sb = new StringBuilder(); + + if ( SpigotPrison.getInstance().isSellAllEnabled() ) { + + final long nanoStart = System.nanoTime(); + + boolean isUsingSign = false; + boolean completelySilent = false; + boolean notifyPlayerEarned = false; + boolean notifyPlayerDelay = false; + boolean notifyPlayerEarningDelay = true; + boolean playSoundOnSellAll = false; + boolean notifyNothingToSell = false; + + boolean success = SellAllUtil.get().sellAllSell( getPlayer(), + isUsingSign, completelySilent, + notifyPlayerEarned, notifyPlayerDelay, + notifyPlayerEarningDelay, playSoundOnSellAll, + notifyNothingToSell, null ); + final long nanoStop = System.nanoTime(); + double milliTime = (nanoStop - nanoStart) / 1000000d; + + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + + sb.append( "(" ) + .append( description) + .append( ": " + (success ? "success" : "failed")) + .append( " ms: " + dFmt.format( milliTime ) + ") "); + } + + return sb.toString(); + } + + public Mine getMine() { return mine; } @@ -382,6 +464,13 @@ public boolean isForceAutoSell() { public void setForceAutoSell( boolean forceAutoSell ) { this.forceAutoSell = forceAutoSell; } + + public boolean isForceBlockRemoval() { + return forceBlockRemoval; + } + public void setForceBlockRemoval(boolean forceBlockRemoval) { + this.forceBlockRemoval = forceBlockRemoval; + } public BlockBreakPriority getBbPriority() { return bbPriority; @@ -433,4 +522,26 @@ public void setDebugInfo(StringBuilder debugInfo) { this.debugInfo = debugInfo; } + public boolean isForceDebugLogging() { + return forceDebugLogging; + } + public void setForceDebugLogging(boolean forceDebugLogging) { + this.forceDebugLogging = forceDebugLogging; + } + + public void setDebugColorCodeInfo() { + getDebugInfo().append( Output.get().getColorCodeInfo() ); + } + + public void setDebugColorCodeWarning() { + getDebugInfo().append( Output.get().getColorCodeWarning() ); + } + + public void setDebugColorCodeError() { + getDebugInfo().append( Output.get().getColorCodeError() ); + } + + public void setDebugColorCodeDebug() { + getDebugInfo().append( Output.get().getColorCodeDebug() ); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java index f6a11d90a..3cb826a75 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.api; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.TreeMap; @@ -11,6 +12,7 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.PrisonBlock; @@ -30,8 +32,10 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.spigot.sellall.SellAllData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.util.ChatColor; import tech.mcprison.prison.util.Location; @@ -43,6 +47,10 @@ *

Use of these are at your own risk. Misuse can result in corruption of Prison's * internal data. *

+ * + *

If you need something special, then please ask on our discord server and we + * can probably provide it for you. + *

* */ public class PrisonSpigotAPI { @@ -431,15 +439,36 @@ public double getSellAllMultiplier(Player player){ * @return BackpaacksUtil - Null if Prison Backpacks are disabled. * */ public BackpacksUtil getPrisonBackpacks(){ - if (SpigotPrison.getInstance().getConfig().getString("backpacks") != null && SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true")){ + if (SpigotPrison.getInstance().getConfig().getString("backpacks") != null && + SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true")){ return BackpacksUtil.get(); } return null; } /** - * Get the whole SellAllUtil of Prison Sellall to manage what you + *

Get the whole SellAllUtil of Prison Sellall to manage what you * want of Prison SellAll. + *

+ * + *

WARNING: usage of this object is at your own risk! Functions will change, + * and will be eliminated. The majority of the functions that were in, and are + * in this object that are `public` were never intended to be used outside + * of prison. Many of the functions really should have been marked as private. + *

+ * + *

WARNING: The sellall functions will be undergoing major revisions and + * improvements in the near future. As such, do not rely on internal functions + * unless otherwise indicated. Some of the features that will be changing, is the + * support for all of prison's items and blocks, including custom blocks and items. + * Also Prison will be adding a very dynamic shop that will allow customization + * for each player rank, if desired. Hence why you should be careful when not using + * this API class. + *

+ * + *

It is highly suggested to use the exposed functions within this API class. + * As such, more have been added to get a variety of different data out of prison. + *

* * @return SellAllUtil - Null if Prison Sellall's disabled. * */ @@ -460,20 +489,644 @@ public SellAllUtil getPrisonSellAll(){ * * @param player * @return - * */ + */ + @Deprecated public Double getSellAllMoneyWithMultiplier(Player player){ + Double results = null; + - if (sellAll == null){ - sellAll = SpigotPrison.getInstance().getSellAllUtil(); - } + if (getPrisonSellAll() != null) { + + double value = 0; + + List soldItems = getPrisonSellAll().sellPlayerItems( player ); + for (SellAllData soldItem : soldItems) { + if ( soldItem != null ) { + value += soldItem.getTransactionAmount(); + } + } + +// return sellAll.getSellMoney(player); + results = value; + } + + return results; + } + + + + /** + *

This function will use Prison internals to pay a player a given sum of money as specified + * by the amount. If the currency is non-standard, then you can also specify it's name as a + * String value; otherwise pass a null or an empty String. Example of non-standard currencies + * would be alternative currencies setup on ranks. + *

+ * + *

This function will notify the player each time they are paid of the payment amount + * (notifyPlayerEarned). It will also play a payment sound (playSoundOnSellAll), the sound can + * be changed within the SellAll config file. + *

+ * + *

If you need to delay player notifications, please use the other `payPlayer()` functions. + *

+ * + *

Prison's internals keep track of the player's balance in the Prison's player cache. It + * allows for rapid payments to a player, without overwhelming Vault or the Economy plugins. + * Some economy plugins will update their database with each hit, which can result in a + * serious performance drain on the system, since such I/O is blocking, and if they run those + * updates in bukkit's main thread. Since prison is caching the payments, as soon as it + * receives a payment, prison starts a count down to make the payment. Any additional payment + * made to a player before that count down reaches zero, will be included in the transaction. + * Rapid mining can create TONS of transactions per second, so Prison's payment cache is + * an important component to help weaker economy plugins from killing the server's TPS. + *

+ * + * @param player + * @param amount + * @param currency - If standard, pass null or an empty String + */ + public void payPlayer( Player player, double amount, String currency ) { + payPlayer( player, amount, currency, true, false, false, true ); + } + + /** + *

This function will use Prison internals to pay a player a given sum of money as specified + * by the amount. This function is the same as the other one that is similar, except that it + * provides more options such as delayed notifications. Please see the help on the other + * `payPlayer()` functions to better understand what they are doing. + *

+ * + *

The payment amount must be greater than zero. If the amount is zero, or less, + * then this function will end silently without any notification. + *

+ * + *

This function has additional parameters for controlling player notifications. If they + * are all set to false, then no notifications will be sent to the player (completelySilent). + *

+ * + *

'notifyPlayerEarned': This function will notify the player each time they are paid + * of the payment amount (notifyPlayerEarned). It will also play a payment + * sound (playSoundOnSellAll), the sound can be changed within the SellAll config file. + *

+ * + *

'notifyPlayerDelay' & SellAll Delay (cooldown): If the SellAll configuration + * `isSellAllDelayEnabled` is set to `true`, then + * the player will be subjected to a cooldown for using the sellall command/feature. + * If the have tried to sell within the allocated amount of time, then they will get a + * message indicating that there is a rate limit in effect for them. They will get + * this notification if the parameter 'notifyPlayerDelay' is set to `true`. + *

+ * + *

Please NOTE: This function, `payPlayer()` only activates the cooldown timer and + * the player will be paid. What is impacted is the ability to use the functions + * `sellAllSell()`... it is then when the rate limit will kick in. If you use the + * other function `sellPlayerItems()` or `sellPlayerItemStacks()` then the + * cooldown rate limit will be bypassed and will not inhibit any selling. + *

+ * + *

'notifyPlayerEarningDelay': If in the SellAll config, the option + * `isAutoSellEarningNotificationDelayEnabled` is enabled, then this parameter + * `notifyPlayerEarningDelay` will then add the amount the player was paid to + * a delayed queue which will gather other payments the player receives during the + * delayed period. At the end of this delayed period of time, then the player + * will get a message indicating the total amount of money that they earned. + * This helps to reduce the amount of spam the player will get on line for their + * sales. Please NOTE: This does not delay the player from getting paid. If the + * delay is set to 15 seconds and they mine 100 times, they will get only one + * message with the total amount that they earned; otherwise they would have been + * sent 100 messages each time something was sold. + *

+ * + *

`playSoundOnSellAll`: If enabled, then a sound will be played upon a payment + * to the player. Please see the SellAll configuration file for changing + * the settings for the sound. + *

+ * + *

`completelySilent`: This is a virtual setting that is generated when all four + * of these settings are set to false: `notifyPlayerEarned`, `notifyPlayerDelay`, + * `notifyPlayerEarningDelay`, and `playSoundOnSellAll`. When enabled, this + * basically shuts off all notifications and the player is paid silently in the + * background. + * + * @param player + * @param amount + * @param currency + * @param notifyPlayerEarned + * @param notifyPlayerDelay + * @param notifyPlayerEarningDelay + * @param playSoundOnSellAll + */ + public void payPlayer( Player player, double amount, String currency, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll ) { + + if ( amount > 0 ) { + + boolean completelySilent = notifyPlayerEarned || notifyPlayerDelay || notifyPlayerEarningDelay || playSoundOnSellAll; + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); + + currency = currency != null && currency.equalsIgnoreCase("default") ? null : currency; + +// if (!sellInputArrayListOnly) { +// removeSellableItems(p); +// } + rankPlayer.addBalance(currency, amount); + + if ( getPrisonSellAll().isSellAllDelayEnabled ){ + getPrisonSellAll().addToDelay(player); + } + + if (!completelySilent) { + if ( getPrisonSellAll().isSellAllSoundEnabled && playSoundOnSellAll) { + player.playSound( player.getLocation(), getPrisonSellAll().sellAllSoundSuccess, 3, 1); + } + + if (notifyPlayerEarningDelay && getPrisonSellAll().isAutoSellEarningNotificationDelayEnabled){ + if (!getPrisonSellAll().isPlayerWaitingAutoSellNotification( player )){ + getPrisonSellAll().addToAutoSellNotificationDelay( player); + } else { + getPrisonSellAll().addDelayedEarningAutoSellNotification( player, amount ); + } + } + else if (notifyPlayerEarned){ + DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); + String amt = fFmt.format( amount ); + + String message = getPrisonSellAll().sellallAmountEarnedMsg( amt ); + +// String message = messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + amt; +// new SpigotPlayer(p).setActionBar( message ); + Output.get().send( sPlayer, message ); + + } + } + } + } + + + /** + *

This function will use Prison internals to pay a player a given sum of money as specified + * by the amount. This function is the same as the other ones with the same name and similar + * parameters. This one differs in that you can pass it a List of `SellAllData` transactions + * and it will summarize them all, and pass the total amount to the other + * `payPlayer()` function. Please see the help on the other + * `payPlayer()` functions to better understand what they are doing. + *

+ * + * @param player + * @param itemsSold + * @param currency + * @param notifyPlayerEarned + * @param notifyPlayerDelay + * @param notifyPlayerEarningDelay + * @param playSoundOnSellAll + */ + public void payPlayer( Player player, List itemsSold, String currency, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll ) { + double amount = 0; + + for (SellAllData item : itemsSold) { + amount += item.getTransactionAmount(); + } + + payPlayer(player, amount, currency, + notifyPlayerEarned, + notifyPlayerDelay, notifyPlayerEarningDelay, + playSoundOnSellAll); + } + + + /** + *

This function will calculate the value of all sellable items within the player's inventory + * and provide a total amount that they earned for the sales. + * This includes the calculated player's multipliers. + *

+ * + * @param player + * @return + */ + public double getPlayerInventoryValue(Player player) { + double results = 0; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getPlayerInventoryValue( new SpigotPlayer(player) ); + } + + return results; + } + + /** + *

This function will calculate the value of the player's inventory that + * are sellable and then will generate + * a simple report listing everything that can be sold with their values. + *

+ * + *

Nothing is sold. No notifications are sent to the player. + *

+ * + *

See the function

getPlayerInventoryValueTransactions()
to + * gain access to the transaction logs for more information. + *

+ * + * @param player + * @return + */ + public String getPlayerInventoryValueReport(Player player) { + String results = null; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getPlayerInventoryValueReport( new SpigotPlayer(player) ); + } + + return results; + } + + /** + *

This function calculates the value of the player's inventory items that are salable, + * and returns the transaction log within the collection of SellAllData. + *

+ * + *

Nothing is sold. No notifications are sent to the player. + *

+ * + *

To get the total transaction value, add all elements together. + * To generate a transaction report use the static function: + *

+ *
List itemsSold = prisonApi.getPlayerInventoryValueTransactions(Player player);
+	 *SellAllData.itemSoldReport( itemsSold );
+ * + * @param player + * @return transactionLogs + */ + public List getPlayerInventoryValueTransactions(Player player) { + List results = new ArrayList<>(); + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getPlayerInventoryValueTransactions( new SpigotPlayer(player) ); + } + + return results; + } + + + /** + *

This function will calculate the value of ItemStack + * and provide a total amount that would earn for the sales. + * This includes the calculated player's multipliers. + *

+ * + * @param player + * @param itemStack + * @return + */ + public double getItemStackValue(Player player, ItemStack itemStack ) { + double results = 0; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getItemStackValue( + new SpigotPlayer(player), new SpigotItemStack(itemStack) ); + + } + + return results; + } + + /** + *

This function will calculate the value of the ItemStack that + * are sellable and then will generate + * a simple report listing everything that can be sold with their values. + *

+ * + *

Nothing is sold. No notifications are sent to the player. + *

+ * + *

See the function

getPlayerInventoryValueTransactions()
to + * gain access to the transaction logs for more information. + *

+ * + * @param player + * @param itemStack + * @return + */ + public String getItemStackValueReport(Player player, ItemStack itemStack ) { + String results = null; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getItemStackValueReport( + new SpigotPlayer(player), new SpigotItemStack(itemStack) ); + + } + + return results; + } + + /** + *

This function calculates the value of the ItemStack that are salable, + * and returns the transaction log within the collection of SellAllData. + *

+ * + *

Nothing is sold. No notifications are sent to the player. + *

+ * + *

To get the total transaction value, add all elements together. + * To generate a transaction report use the static function: + *

+ *
List itemsSold = prisonApi.getPlayerInventoryValueTransactions(Player player);
+	 *SellAllData.itemSoldReport( itemsSold );
+ * + * @param player + * @param itemStack + * @return + */ + public List getItemStackValueTransactions(Player player, ItemStack itemStack ) { + List results = new ArrayList<>(); + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().getItemStackValueTransactions( + new SpigotPlayer(player), new SpigotItemStack(itemStack) ); + + } + + return results; + } - if (sellAll != null){ - return sellAll.getSellMoney(player); + /** + *

This function sells anything within the player's inventory that is + * sellable. This function returns a transaction log of soldItems that can + * be summarized to get the total sales amount.

+ * + *

WARNING: This function REMOVES items from the player's inventory, but does + * NOT pay them any money!! If you are using this function, then + * you must sum all of the transactions and pay the player. + *

+ * + *

This is an exposed internal function that provides sellall capabilities without + * all of the complexities of the formal `sellAllSell()` functions. + * Use at your own risk. + *

+ * + *

This function does not notify the players, does not pay the players, + * does not provide all of the bells-and-whistles of customization within the + * sellall config files, and is basically a bare-bones sell it if it can be sold + * type of function. + *

+ * + * @param player + * @param itemStack + * @return + */ + public List sellPlayerItems(Player player ) { + List soldItems = new ArrayList<>(); + + if (getPrisonSellAll() != null) { + + soldItems = getPrisonSellAll().sellPlayerItems( player ); } + + return soldItems; + } - return null; + /** + *

This function sells anything within the ItemStack List that is + * sellable. This function returns a transaction log of soldItems that can + * be summarized to get the total sales amount.

+ * + *

WARNING: This function REMOVES items from the ItemStack that have been + * sold, but does NOT pay the player any money!! If you are + * using this function, then you must sum all of the + * transactions and pay the player. + *

+ * + *

This is an exposed internal function that provides sellall capabilities without + * all of the complexities of the formal `sellAllSell()` functions. + * Use at your own risk. + *

+ * + *

This function does not notify the players, does not pay the players, + * does not provide all of the bells-and-whistles of customization within the + * sellall config files, and is basically a bare-bones sell it if it can be sold + * type of function. + *

+ * + * @param player + * @param itemStacks + * @return + */ + public List sellPlayerItemStacks(Player player, List itemStacks ) { + List soldItems = new ArrayList<>(); + + if (getPrisonSellAll() != null) { + + List iStacks = new ArrayList<>(); + for (ItemStack itemStack : itemStacks) { + if ( itemStack != null ) { + iStacks.add( new SpigotItemStack( itemStack )); + } + } + + soldItems = getPrisonSellAll().sellPlayerItemStacks( player, iStacks ); + } + + return soldItems; } + + /** + *

This function will remove all sellable items from the player's Inventories. It will first ensure that a + * Player can sell the items. Some of the conditions that are checked are, along with some of the behaviors: + *

+ * + *
    + *
  • If player has access to use SellAll signs.
  • + *
  • Provide the amount the player earned if this is not disabled.
  • + *
  • If this actions is silenced, then text and audio notifications are suppressed.
  • + *
  • If configured, the reported earnings amount may be delayed and added to other earnings, + * which will reduce flooding the player with notifications.
  • + *
  • If sound notifications are enabled, then they will be played.
  • + * + *
+ * + *

Default usage of this method: + *

+ *
sellAllSell(p, false, false, true, true, false, true);
+ * + * @param p - Player. + * @param isUsingSign - boolean. + * @param completelySilent - boolean. + * @param notifyPlayerEarned - boolean. + * @param notifyPlayerDelay - boolean. + * @param notifyPlayerEarningDelay - boolean. + * @param playSoundOnSellAll - boolean. + * + * @return boolean If successful + * */ + public boolean sellAllSell(Player p, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll) { + boolean results = false; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().sellAllSell( p, + isUsingSign, + completelySilent, + notifyPlayerEarned, + notifyPlayerDelay, + notifyPlayerEarningDelay, + playSoundOnSellAll, + null ); + } + + return results; + } + + /** + *

Performs a sellall of the player's inventory. + *

+ * + * @param p + * @param isUsingSign + * @param completelySilent + * @param notifyPlayerEarned + * @param notifyPlayerDelay + * @param notifyPlayerEarningDelay + * @param playSoundOnSellAll + * @param amounts + * @return + */ + public boolean sellAllSell(Player p, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll, + List amounts ){ + boolean results = false; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().sellAllSell( p, + isUsingSign, completelySilent, + notifyPlayerEarned, notifyPlayerDelay, + notifyPlayerEarningDelay, playSoundOnSellAll, + amounts ); + } + + return results; + } + + /** + *

This function performs the sellall functions over an ItemStack. + *

+ * + * @param p + * @param itemStack + * @param completelySilent + * @param notifyPlayerEarned + * @param notifyPlayerEarningDelay + * @return + */ + public double sellAllSell(Player p, + SpigotItemStack itemStack, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerEarningDelay) + { + double results = 0; + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().sellAllSell( p, + itemStack, + completelySilent, + notifyPlayerEarned, + notifyPlayerEarningDelay ); + } + + return results; + } + + + + /** + * Sell removing items from Inventories and checking all the possible conditions that a Player must meet to sell + * items, this includes method parameters like: + * - Is using SellAll Sign. + * - If tell the Player how much did he earn (if this's disabled by config, the parameter will be ignored). + * - If do this action without making the player notice it, disabling sounds and all messages. + * - If tell the Player to wait the end of SellAll Delay if not ended (if this's disabled by config, the parameter will be ignored). + * - If tell the Player how much did he earn only after a delay (AutoSell Delay Earnings will use this option for example). + * - If play sound on SellAll Sell (If sounds are disabled from the config, this parameter will be ignored. + * - If Sell only stuff from the input arrayList and not sell what is in the many Player inventories and supported backpacks. + * + * NOTE: With this method you can add an ArrayList of ItemStacks to sell, remove sold items (this will return the ArrayList without + * sold items), and give money to the player, also note that this will also trigger the usual sellall sell and sell everything sellable + * from all inventories and enabled backpacks of the Player. + * + * Return True if success, False if error or nothing changed or Player not meeting requirements. + * + * Default usage of this method: sellAllSell(p, itemStacks, false, false, true, false, false, true, false); + * + * @param p - Player. + * @param itemStacks - ArrayList of ItemStacks. + * @param isUsingSign - boolean. + * @param completelySilent - boolean. + * @param notifyPlayerEarned - boolean. + * @param notifyPlayerDelay - boolean. + * @param notifyPlayerEarningDelay - boolean. + * @param playSoundOnSellAll - boolean. + * @param sellInputArrayListOnly - boolean. + * + * @return Array of ItemStacks + * */ + public ArrayList sellAllSell(Player p, + ArrayList itemStacks, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll, + boolean sellInputArrayListOnly){ + + ArrayList results = new ArrayList<>(); + + if (getPrisonSellAll() != null) { + + results = getPrisonSellAll().sellAllSell( p, + itemStacks, + isUsingSign, + completelySilent, + notifyPlayerEarned, + notifyPlayerDelay, + notifyPlayerEarningDelay, + playSoundOnSellAll, + sellInputArrayListOnly); + } + + return results; + } + + + /** *

Gets a player's current token balance. *

diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java index cf6ef2e0c..5da51a904 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java @@ -76,13 +76,16 @@ public void run() { int count = 0; for ( SpigotBlock spigotBlock : blocks ) { - if ( count++ % 10 == 0 && mineStateMutexClone != null && - !mine.getMineStateMutex().isValidState( mineStateMutexClone ) ) { - return; + if ( spigotBlock != null && !spigotBlock.isEmpty() ) { + + if ( count++ % 10 == 0 && mineStateMutexClone != null && + !mine.getMineStateMutex().isValidState( mineStateMutexClone ) ) { + return; + } + + spigotBlock.setPrisonBlock( PrisonBlock.AIR ); + } - - spigotBlock.setPrisonBlock( PrisonBlock.AIR ); - } } } 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 841fbae06..79da13c74 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 @@ -8,6 +8,7 @@ import java.util.Map.Entry; import java.util.Random; import java.util.Set; +import java.util.TreeMap; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -17,15 +18,20 @@ import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.event.EventException; import org.bukkit.event.HandlerList; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.plugin.RegisteredListener; import com.cryptomorin.xseries.XMaterial; +import com.vk2gpz.tokenenchant.api.TokenEnchantAPI; import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.autofeatures.BlockConverterOptionEventTrigger; import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; @@ -33,6 +39,8 @@ import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.Output.DebugTarget; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; @@ -152,9 +160,20 @@ protected void printDebugInfo( PrisonMinesBlockBreakEvent pmEvent, double start if ( pmEvent != null && pmEvent.getDebugInfo().length() > 0 ) { long stop = System.nanoTime(); - pmEvent.getDebugInfo().append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + pmEvent.getDebugInfo().append( "{br}|| ### ** End Event Debug Info ** ### [" ) + .append( (stop - start) / 1000000d ) + .append( " ms]" ); - Output.get().logDebug( DebugTarget.blockBreak, pmEvent.getDebugInfo().toString() ); + if ( !Output.get().isDebug() && pmEvent.isForceDebugLogging() ) { + + pmEvent.getDebugInfo().insert(0, Output.get().getColorCodeDebug() ); + + Output.get().logInfo( pmEvent.getDebugInfo().toString(), pmEvent.getSpigotPlayer() ); + } + else { + + Output.get().logDebug( DebugTarget.blockBreak, pmEvent.getDebugInfo().toString(), pmEvent.getSpigotPlayer() ); + } } } @@ -236,7 +255,7 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv if ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines ) ) { - pmEvent.getDebugInfo().append( "(normal processing initiating) " ); + pmEvent.getDebugInfo().append( "(Fire pmEvent) " ); // 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. @@ -256,8 +275,11 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv // pmEvent.getMine(), sBlock, explodedBlocks, BlockEventType.blockBreak, triggered ); Bukkit.getServer().getPluginManager().callEvent( pmEvent ); if ( pmEvent.isCancelled() ) { + + pmEvent.setDebugColorCodeWarning(); pmEvent.getDebugInfo().append( - "(normal processing: PrisonMinesBlockBreakEvent was canceled by another plugin!) " ); + "(Fire pmEvent: PrisonMinesBlockBreakEvent was canceled by another plugin!) " ); + pmEvent.setDebugColorCodeDebug(); } else { @@ -287,17 +309,19 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv } else { - pmEvent.getDebugInfo().append( "(doAction failed without details) " ); + pmEvent.setDebugColorCodeWarning(); + pmEvent.getDebugInfo().append( "(fire pmEvent:doAction failed without details) " ); + pmEvent.setDebugColorCodeDebug(); } } - pmEvent.getDebugInfo().append( "(normal processing completed) " ); + pmEvent.getDebugInfo().append( "(Fire pmEvent completed) " ); } else { - pmEvent.getDebugInfo().append( "(logic bypass) " ); + pmEvent.getDebugInfo().append( "(Fire pmEvent bypassed) " ); } return cancelBy; } @@ -359,15 +383,35 @@ protected boolean hasFortune(SpigotItemStack itemInHand){ return results; } - protected short getFortune(SpigotItemStack itemInHand, StringBuilder debugInfo ){ - short fortLevel = (short) 0; + protected int getFortune(SpigotItemStack itemInHand, StringBuilder debugInfo ){ + int fortLevel = 0; + boolean usedTEFortune = false; + + if ( isBoolean( AutoFeatures.isUseTokenEnchantsFortuneLevel ) && + itemInHand != null && + itemInHand.getBukkitStack() != null ) { + + try { + if ( TokenEnchantAPI.getInstance() != null ) { + + fortLevel = TokenEnchantAPI.getInstance().getEnchantments( itemInHand.getBukkitStack() ) + .get( TokenEnchantAPI.getInstance().getEnchantment("Fortune")); + + usedTEFortune = true; + } + } + catch ( Exception e ) { + // ignore: could not use TE. + } + } try { - if ( itemInHand != null && + if ( !usedTEFortune && + itemInHand != null && itemInHand.getBukkitStack() != null && itemInHand.getBukkitStack().containsEnchantment( Enchantment.LOOT_BONUS_BLOCKS ) && itemInHand.getBukkitStack().getEnchantments() != null ) { - fortLevel = (short) itemInHand.getBukkitStack().getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); + fortLevel = itemInHand.getBukkitStack().getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); } } catch ( NullPointerException e ) { @@ -375,14 +419,14 @@ protected short getFortune(SpigotItemStack itemInHand, StringBuilder debugInfo ) // It throws this exception: Caused by: java.lang.NullPointerException: null key in entry: null=5 } - short results = (short) fortLevel; + int results = fortLevel; // DecimalFormat dFmt = new DecimalFormat( "#,##0.0000" ); DecimalFormat iFmt = new DecimalFormat( "#,##0" ); int maxFortuneLevel = getInteger( AutoFeatures.fortuneMultiplierMax ); String maxFort = ""; if ( maxFortuneLevel > 0 && fortLevel > maxFortuneLevel ) { - results = (short) maxFortuneLevel; + results = maxFortuneLevel; maxFort = String.format(" max=%s result=%s", iFmt.format( maxFortuneLevel ), iFmt.format( results )); @@ -470,12 +514,13 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { boolean loreSmelt = isLoreEnabled && checkLore( itemInHand, getMessage( AutoFeatures.loreSmeltValue) ); boolean loreBlock = isLoreEnabled && checkLore( itemInHand, getMessage( AutoFeatures.loreBlockValue ) ); - boolean permPickup = player.isPermissionSet( getMessage( AutoFeatures.permissionAutoPickup )); - boolean permSmelt = player.isPermissionSet( getMessage( AutoFeatures.permissionAutoSmelt )); - boolean permBlock = player.isPermissionSet( getMessage( AutoFeatures.permissionAutoBlock )); - boolean isAutoFeaturesEnabled = isBoolean( AutoFeatures.isAutoFeaturesEnabled ); + boolean permPickup = isAutoFeaturesEnabled && player.isPermissionSet( getMessage( AutoFeatures.permissionAutoPickup )); + boolean permSmelt = isAutoFeaturesEnabled && player.isPermissionSet( getMessage( AutoFeatures.permissionAutoSmelt )); + boolean permBlock = isAutoFeaturesEnabled && player.isPermissionSet( getMessage( AutoFeatures.permissionAutoBlock )); + + boolean configPickup = isAutoFeaturesEnabled && isBoolean( AutoFeatures.autoPickupEnabled ); boolean configSmelt = isAutoFeaturesEnabled && isBoolean( AutoFeatures.autoSmeltEnabled ); boolean configBlock = isAutoFeaturesEnabled && isBoolean( AutoFeatures.autoBlockEnabled ); @@ -504,11 +549,16 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { if ( Output.get().isDebug( DebugTarget.blockBreak ) ) { - pmEvent.getDebugInfo().append( "(applyAutoEvents: " ) + pmEvent.getDebugInfo().append( "{br}|| (applyAutoEvents: " ) .append( pmEvent.getSpigotBlock().getBlockName() ); if ( !isAutoFeaturesEnabled ) { - pmEvent.getDebugInfo().append("isAutoFeaturesEnabled=false (disabled)"); + pmEvent.getDebugInfo().append(" isAutoFeaturesEnabled=false ("); + + pmEvent.getDebugInfo().append( Output.get().getColorCodeError() ); + pmEvent.getDebugInfo().append("disabled"); + pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug() ); + pmEvent.getDebugInfo().append(")"); } else { @@ -563,7 +613,7 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { if ( configNormalDrop ) { pmEvent.getDebugInfo() - .append( "(NormalDrop handling enabled: " ) + .append( "{br}|| (NormalDrop handling enabled: " ) .append( "normalDropSmelt[" ) .append( configNormalDropSmelt ? "enabled" : "disabled" ) .append( "] " ) @@ -755,7 +805,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, .append( amt ); if ( amt != amtBukkit ) { sItemStack.setAmount( amt ); - sb.append( "(").append( amtBukkit ).append( ")" ); + sb.append( "(bukkitAmt:").append( amtBukkit ).append( ")" ); } } if ( bukkitDropsMultiplier != 1.0d ) { @@ -764,7 +814,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, sb.insert( 0, "bukkitDropMult=" ); } - debugInfo.append( "[autoPickupDrops:: " ).append( sb ).append( "] "); + debugInfo.append( " [autoPickupDrops:beforeFortune:: " ).append( sb ).append( "] "); @@ -779,15 +829,24 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // Add fortune to the items in the inventory if ( isBoolean( AutoFeatures.isCalculateFortuneEnabled ) ) { - short fortuneLevel = getFortune(itemInHand, debugInfo ); + sb.setLength(0); + int fortuneLevel = getFortune(itemInHand, debugInfo ); // debugInfo.append( "(calculateFortune: fort " + fortuneLevel + ")" ); for ( SpigotItemStack itemStack : drops ) { + if ( sb.length() > 0 ) { + sb.append( "," ); + } // calculateFortune directly modifies the quantity on the blocks ItemStack: calculateFortune( itemStack, fortuneLevel, pmEvent.getDebugInfo() ); + + sb.append( itemStack.getName() ) + .append( ":" ) + .append( itemStack.getAmount() ); } + debugInfo.append( " [totalDrops:afterFortune:: " ).append( sb ).append( "] "); } @@ -798,14 +857,14 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // Smelt if ( isAutoSmelt ) { - debugInfo.append( "(autoSmelting: itemStacks)" ); + debugInfo.append( "(autoSmelting: drops)" ); normalDropSmelt( drops ); } // Block if ( isAutoBlock ) { - debugInfo.append( "(autoBlocking: itemStacks)" ); + debugInfo.append( "(autoBlocking: drops)" ); normalDropBlock( drops ); } @@ -831,29 +890,70 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, boolean isSellallEnabled = SpigotPrison.getInstance().isSellAllEnabled(); - // This is true if the player cannot toggle the autosell, and it's - // true if they can, and the have it enabled: - boolean isPlayerAutosellEnabled = isSellallEnabled && - SellAllUtil.get() != null && - SellAllUtil.get().checkIfPlayerAutosellIsActive( - pmEvent.getSpigotPlayer().getWrapper() ) - ; +// boolean isPlayerAutoSellTurnedOff = SellAllUtil.get().isAutoSellPerUserToggleable && +// !SellAllUtil.get().isSellallPlayerUserToggleEnabled( +// pmEvent.getSpigotPlayer().getWrapper() ); +// +// if ( isPlayerAutoSellTurnedOff ) { +// debugInfo.append( Output.get().getColorCodeWarning() ); +// debugInfo.append( "(Player toggled off autosell) " ); +// debugInfo.append( Output.get().getColorCodeDebug() ); +// } +// +// // This will return true (allow autosell) unless players can toggle autosell and they turned it off: +// // This is to be used with other auto sell setting, but never on it's own: +// boolean isPlayerAutosellEnabled = +// isSellallEnabled && +// (!SellAllUtil.get().isAutoSellPerUserToggleable || +// SellAllUtil.get().isSellallPlayerUserToggleEnabled( +// pmEvent.getSpigotPlayer().getWrapper() )); + + boolean isPlayerAutosellEnabled = pmEvent.getSpigotPlayer().isAutoSellEnabled( pmEvent.getDebugInfo() ); + + + // In the event, forceAutoSell is enabled, which means the drops must be sold. + // The player's toggle cannot disable this. + boolean forceAutoSell = isSellallEnabled && pmEvent.isForceAutoSell(); + + + // AutoFeature's autosell per block break - global setting + boolean autoSellBySettings = + isPlayerAutosellEnabled && + isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled); + + // AutoFeature's autosell per block break - per player perms setting +// boolean autoSellByPerm = +// isPlayerAutosellEnabled && +// !player.isOp() && +// isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && +// !"disable".equalsIgnoreCase( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) ) && +// !"false".equalsIgnoreCase( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) ) && +// player.hasPermission( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) ); + + boolean autoSellByPerm = pmEvent.getSpigotPlayer().isAutoSellByPermEnabled( isPlayerAutosellEnabled ); + + + // Try to autosell if enabled in any of the following ways: + boolean autoSell = ( forceAutoSell || autoSellBySettings || autoSellByPerm ); for ( SpigotItemStack itemStack : drops ) { count += itemStack.getAmount(); - // Try to autosell if enabled: - if ( isSellallEnabled && - - (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && - isPlayerAutosellEnabled || - pmEvent.isForceAutoSell() || - !player.isOp() && !"disable".equalsIgnoreCase( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) ) && - player.hasPermission( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) )) && - isPlayerAutosellEnabled ) { + // Try to autosell if enabled in any of the following ways: + if ( autoSell ) { + +// // Try to autosell if enabled: +// if ( isSellallEnabled && +// +// (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && +// isPlayerAutosellEnabled || +// pmEvent.isForceAutoSell() || +// !player.isOp() && !"disable".equalsIgnoreCase( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) ) && +// player.hasPermission( getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ) )) && +// isPlayerAutosellEnabled ) { final long nanoStart = System.nanoTime(); double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); @@ -875,7 +975,9 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, else { // Unable to sell since amount was zero. Not configured to be sold. + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(unsellable: " + itemStack.getName() + " qty: " + itemStack.getAmount() + ") "); + pmEvent.setDebugColorCodeDebug(); autosellUnsellableCount += itemStack.getAmount(); } @@ -887,13 +989,39 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // it will have an amount of more than 0. if ( itemStack.getAmount() > 0 ) { + + // AutoSell failure... some items may be unsellable due to not being setup in the sellall shop: + if ( forceAutoSell || autoSellBySettings || autoSellByPerm ) { + + // Force debug printing for this entry even if debug mode is turned off: + pmEvent.setForceDebugLogging( true ); + + if ( !Output.get().isDebug() && + isBoolean(AutoFeatures.isAutoSellLeftoversForceDebugLogging) ) { + pmEvent.setForceDebugLogging( true ); + } + + pmEvent.setDebugColorCodeError(); + + // Just get the calculated value for the drops... do not sell: + double amount = SellAllUtil.get().getItemStackValue( pmEvent.getSpigotPlayer(), itemStack ); + autosellTotal += amount; + + debugInfo.append( "{br}|| (WARNING: autosell leftovers: " + itemStack.getName() + + " qty: " + itemStack.getAmount() + " value: " + dFmt.format( amount ) + + " - " + + ( amount == 0 ? " Items NOT in sellall shop!" : " CouldNotSell?") + + ") "); + pmEvent.setDebugColorCodeDebug(); + } + if ( Output.get().isDebug() && isSellallEnabled ) { // Just get the calculated value for the drops... do not sell: - double amount = SellAllUtil.get().getSellMoney( player, itemStack ); + double amount = SellAllUtil.get().getItemStackValue( pmEvent.getSpigotPlayer(), itemStack ); autosellTotal += amount; - debugInfo.append( "(Debug-unsold-value-check: " + itemStack.getName() + + debugInfo.append( " (Debug-unsold-value-check: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + dFmt.format( amount ) + ") "); } @@ -920,7 +1048,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // } - dropExtra( extras, player, debugInfo ); + dropExtra( extras, player, debugInfo, autoSell ); // dropExtra( player.getInventory().addItem(itemStack), player, block ); } @@ -929,7 +1057,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, if ( count > 0 || autosellTotal > 0 ) { - debugInfo.append( "[autoPickupDrops total: qty: " + count + " value: " + dFmt.format( autosellTotal ) + + debugInfo.append( "{br}|| [autoPickupDrops total: qty: " + count + " value: " + dFmt.format( autosellTotal ) + " unsellableCount: " + autosellUnsellableCount ); if ( nanoTime > 0 ) { @@ -1012,11 +1140,11 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { sb.insert( 0, "bukkitDropMult=" ); } - pmEvent.getDebugInfo().append( "[normalDrops:: " ).append( sb ).append( "] "); + pmEvent.getDebugInfo().append( "{br}|| [normalDrops:: " ).append( sb ).append( "] "); // Need better drop calculation that is not using the getDrops function. - short fortuneLevel = getFortune( pmEvent.getItemInHand(), pmEvent.getDebugInfo() ); + int fortuneLevel = getFortune( pmEvent.getItemInHand(), pmEvent.getDebugInfo() ); // calculateSilkTouch( pmEvent.getItemInHand(), drops ); @@ -1040,13 +1168,13 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { if ( isBoolean( AutoFeatures.normalDropSmelt ) ) { - pmEvent.getDebugInfo().append( "(normSmelting: itemStacks)" ); + pmEvent.getDebugInfo().append( "(normSmelting: drops)" ); normalDropSmelt( drops ); } if ( isBoolean( AutoFeatures.normalDropBlock ) ) { - pmEvent.getDebugInfo().append( "(normBlocking: itemStacks)" ); + pmEvent.getDebugInfo().append( "(normBlocking: drops)" ); normalDropBlock( drops ); } @@ -1063,6 +1191,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { // } +// pmEvent.getDebugInfo().append( "{br}|| " ); double autosellTotal = 0; @@ -1072,7 +1201,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { count += itemStack.getAmount(); // Since this is not auto pickup, then only autosell if set in the pmEvent: - if ( pmEvent.isForceAutoSell() && SellAllUtil.get() != null ) { + if ( pmEvent.isForceAutoSell() && SpigotPrison.getInstance().isSellAllEnabled() ) { Player player = pmEvent.getPlayer(); @@ -1097,7 +1226,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { pmEvent.getDebugInfo().append( "(dropping: " + itemStack.getName() + " qty: " + itemStack.getAmount() ); - if ( SellAllUtil.get() != null ) { + if ( SpigotPrison.getInstance().isSellAllEnabled() ) { double amount = SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); autosellTotal += amount; @@ -1115,7 +1244,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { if ( count > 0 || autosellTotal > 0 ) { - pmEvent.getDebugInfo().append( "[normalDrops total: qty: " + count + " value: " + autosellTotal + ") "); + pmEvent.getDebugInfo().append( "{br}|| [normalDrops total: qty: " + count + " value: " + autosellTotal + "] "); } @@ -1316,7 +1445,8 @@ protected boolean checkLore( SpigotItemStack itemInHand, String loreValue ) { * @param player * @param block */ - protected void dropExtra( HashMap extra, Player player, StringBuilder debugInfo ) { + protected void dropExtra( HashMap extra, + Player player, StringBuilder debugInfo, boolean autoSell ) { if ( SpigotPrison.getInstance().isSellAllEnabled() && ( extra != null && extra.size() > 0 || @@ -1326,17 +1456,39 @@ protected void dropExtra( HashMap extra, Player player // if ( SpigotPrison.getInstance().isSellAllEnabled() ) { + SpigotPlayer sPlayer = new SpigotPlayer( player ); + + boolean isPlayerAutosellEnabled = sPlayer.isAutoSellEnabled( debugInfo ); + + boolean isPlayerAutoSellByPerm = sPlayer.isAutoSellByPermEnabled( isPlayerAutosellEnabled ); + + if ( isPlayerAutosellEnabled || isPlayerAutoSellByPerm ) { + + SellAllUtil sellAllUtil = SellAllUtil.get(); - SellAllUtil sellAllUtil = SellAllUtil.get(); +// boolean isSellallEnabled = sellAllUtil != null && +// SpigotPrison.getInstance().isSellAllEnabled(); +// +// // This will return true (allow autosell) unless players can toggle autosell and they turned it off: +// // This is to be used with other auto sell setting, but never on it's own: +// boolean isPlayerAutosellEnabled = +// isSellallEnabled && +// (!sellAllUtil.isAutoSellPerUserToggleable || +// sellAllUtil.isSellallPlayerUserToggleEnabled( +// player )); + + - // On inventory is full, will auto sell if auto sell is enabled in either - // the sellall configs, or the auto feature configs. - if (sellAllUtil != null && ( - sellAllUtil.isAutoSellEnabled || - isBoolean(AutoFeatures.isAutoSellIfInventoryIsFull) )) { +// // On inventory is full, will auto sell if auto sell is enabled in either +// // the sellall configs, or the auto feature configs. +// if (sellAllUtil != null && ( +// sellAllUtil.isAutoSellEnabled || +// autoSell )) { +//// isBoolean(AutoFeatures.isAutoSellIfInventoryIsFull) )) { - if ( sellAllUtil.checkIfPlayerAutosellIsActive(player) ) { + // if ( isPlayerAutosellEnabled ) + { boolean saNote = sellAllUtil.isAutoSellNotificationEnabled; @@ -1387,7 +1539,7 @@ protected void dropExtra( HashMap extra, Player player debugInfo.append( " ] " ); - SpigotPlayer sPlayer = new SpigotPlayer( player ); + //SpigotPlayer sPlayer = new SpigotPlayer( player ); PlayerAutoRankupTask.autoSubmitPlayerRankupTask( sPlayer, debugInfo ); } @@ -2592,7 +2744,48 @@ else if ( ); debugInfo.append( msg ); } + + else if ( isBoolean( AutoFeatures.isPercentGradientFortuneEnabled ) ) { + + int bonusBlocks = 0; + double rnd = 1.0; + + double maxFortune = getInteger( AutoFeatures.percentGradientFortuneMaxFortuneLevel ); + int maxBonusBlocks = getInteger( AutoFeatures.percentGradientFortuneMaxBonusBlocks ); + double minPctRnd = getDouble( AutoFeatures.percentGradientFortuneMinPercentRandomness ); + + double fortLevel = fortuneLevelOriginal > maxFortune ? maxFortune : fortuneLevelOriginal; + if ( maxFortune > 0 && maxBonusBlocks > 1 ) { + + minPctRnd = + minPctRnd < 0.0 ? 0.0 : + minPctRnd > 100.00 ? 99.0 : minPctRnd; + + rnd = ((1.0 - (minPctRnd / 100)) * getRandom().nextDouble()) + (minPctRnd / 100); + + + bonusBlocks = (int) Math.round( ( fortLevel / maxFortune ) * maxBonusBlocks ); + + bonusBlocks *= rnd; + } + + // The count has the final value so set it as the amount: + blocks.setAmount( 1 + bonusBlocks ); + + String msg = String.format( + "(gradientFortune blocks: 1 + bonusBlocks=%s == (fortLevel=%s / maxFortLevel=%s) * " + + "maxBonusBlocks=%s * rnd=%s [with minPctRnd=%s]) ", + iFmt.format( bonusBlocks ), + iFmt.format( fortLevel ), + iFmt.format( maxFortune ), + iFmt.format( maxBonusBlocks ), + dFmt.format( rnd ), + dFmt.format( minPctRnd ) + ); + + debugInfo.append( msg ); + } } } @@ -3075,6 +3268,190 @@ private List calculateDropAdditionsGravelFlint(SpigotItemStack return adds; } + public boolean checkBlockConverterEventTrigger(PrisonMinesBlockBreakEvent pmEvent, BlockBreakEvent event ) { + boolean terminate = false; + + long start = System.currentTimeMillis(); + + SpigotPlayer sPlayer = pmEvent.getSpigotPlayer(); +// RankPlayer rPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( pmEvent.getSpigotPlayer() ); + String blockName = pmEvent.getSpigotBlock().getBlockName(); + + List eventTriggers = + AutoFeaturesWrapper.getBlockConvertersInstance().findEventTrigger( sPlayer, blockName ); + + if ( eventTriggers != null ) { + StringBuilder sb = new StringBuilder(); + + for (BlockConverterOptionEventTrigger eventTrigger : eventTriggers) { + RegisteredListener listener = null; + + if ( eventTrigger.getExternalResource() == null ) { + // Try to hook in to the external resource (the plugin listener): + // Adding this listener to the eventTrigger will be like a cache: + + listener = findBlockBreakEventListener( + eventTrigger.getEventPluginName(), + eventTrigger.getEventPluginPriority(), + eventTrigger.getEventPluginClassName() ); + + if ( listener != null ) { + eventTrigger.setExternalResource( listener ); + } + } + + if ( listener == null && eventTrigger.getExternalResource() != null ) { + + listener = (RegisteredListener) eventTrigger.getExternalResource(); + } + + if ( listener != null ) { + + try { + + if ( sb.length() > 0 ) { + sb.append( " " ); + } + sb.append( eventTrigger.getEventPluginName() ); + + // This is where the magic happens... triggers the event listener: + listener.callEvent( event ); + + if ( !eventTrigger.isAllowPrisonToProccessDrops() ) { + terminate = true; + } + + if ( eventTrigger.isRemoveBlockWithoutDrops() ) { + pmEvent.setForceBlockRemoval( true ); + pmEvent.setBbPriority( BlockBreakPriority.MONITOR ); + + finalizeBreakTheBlocks( pmEvent, pmEvent.getSpigotBlock(), pmEvent.getTargetBlock() ); + } + } + catch (EventException e) { + } + } + + } + + long stop = System.currentTimeMillis(); + double durationMs = (stop - start) / 1_000_000.0d; + + DecimalFormat dFmt = new DecimalFormat( "#,##0.000" ); + + String msg = String.format( + "(BlockConverter eventTrigger: %s : %s ms) ", + sb, + dFmt.format( durationMs ) ); + pmEvent.getDebugInfo().append( msg ); + } + + return terminate; + } + + + public void removeBlockForTriggerEvent( PrisonMinesBlockBreakEvent pmEvent) { + + finalizeBreakTheBlocks( pmEvent ); + + } + + public void removeEventTriggerBlocksFromExplosions( PrisonMinesBlockBreakEvent pmEvent ) { + + if ( pmEvent.getUnprocessedRawBlocks().size() > 0 && + AutoFeaturesWrapper.getBlockConvertersInstance().getEventTriggerBlockNames().size() > 0 ) { + + long start = System.currentTimeMillis(); + +// RankPlayer rPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( pmEvent.getSpigotPlayer() ); + + + TreeMap blockCounts = new TreeMap<>(); + + List blockNamesToRemove = AutoFeaturesWrapper.getBlockConvertersInstance().getEventTriggerBlockNames(); + List removeBlocks = new ArrayList<>(); + + for (Block block : pmEvent.getUnprocessedRawBlocks()) { + SpigotBlock sBlock = SpigotBlock.getSpigotBlock( block ); + String blockName = sBlock.getBlockName().toLowerCase(); + + if ( blockNamesToRemove.contains( blockName ) ) { + removeBlocks.add( block ); + + if ( !blockCounts.containsKey(blockName) ) { + blockCounts.put( blockName, 1 ); + } + else { + int count = blockCounts.get( blockName ); + blockCounts.put( blockName, ++count ); + } + } + } + + if ( removeBlocks.size() > 0 ) { + pmEvent.getUnprocessedRawBlocks().removeAll( removeBlocks ); + + +// if ( eventTrigger.isRemoveBlockWithoutDrops() ) { +//// pmEvent.setForceBlockRemoval( true ); +//// pmEvent.setBbPriority( BlockBreakPriority.MONITOR ); +// +// finalizeBreakTheBlocks( pmEvent, pmEvent.getSpigotBlock(), pmEvent.getTargetBlock() ); +// } + } + + + long stop = System.currentTimeMillis(); + double durationMs = (stop - start) / 1_000_000.0d; + + + // Log if blocks were removed, or if duration is >= 0.5: + if ( blockCounts.size() > 0 || durationMs > 0.5 ) { + + StringBuilder sb = new StringBuilder(); + + Set keys = blockCounts.keySet(); + for (String key : keys) { + if ( sb.length() > 0 ) { + sb.append(","); + } + sb.append( key ).append( ":" ).append( blockCounts.get(key).toString() ); + } + + if ( sb.length() == 0 ) { + sb.append( "none" ); + } + DecimalFormat dFmt = new DecimalFormat( "#,##0.000" ); + + String msg = String.format( + "(BlockConverter eventTrigger: blocks removed: [%s] %s ms) ", + sb, + dFmt.format( durationMs ) ); + pmEvent.getDebugInfo().append( msg ); + } + + } + + } + + private RegisteredListener findBlockBreakEventListener( String plugin, String priority, String className ) { + RegisteredListener results = null; + + for ( RegisteredListener listener : BlockBreakEvent.getHandlerList().getRegisteredListeners() ) { + + if ( plugin.equalsIgnoreCase( listener.getPlugin().getName() ) && + priority.equalsIgnoreCase( listener.getPriority().name() ) && + listener.getListener().getClass().getName().endsWith( className ) + ) { + + results = listener; + break; + } + + } + return results; + } + public Random getRandom() { return random; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java index 55dd38947..c5726ea9f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.spigot.autofeatures.events; +import java.util.TreeSet; + import org.bukkit.Bukkit; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -12,6 +14,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.EventExecutor; import org.bukkit.plugin.PluginManager; +import org.bukkit.scheduler.BukkitRunnable; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; @@ -21,6 +24,7 @@ import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; +import tech.mcprison.prison.spigot.game.SpigotPlayer; public class AutoManagerBlockBreakEvents @@ -29,11 +33,19 @@ public class AutoManagerBlockBreakEvents { private BlockBreakPriority bbPriority; + + private TreeSet delayedSellallPlayers; + + public AutoManagerBlockBreakEvents() { super(); + + this.delayedSellallPlayers = new TreeSet<>(); } public AutoManagerBlockBreakEvents( BlockBreakPriority bbPriority ) { super(); + + this.delayedSellallPlayers = new TreeSet<>(); this.bbPriority = bbPriority; } @@ -49,7 +61,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -272,7 +287,7 @@ private void handleBlockBreakEvent( BlockBreakEvent e, BlockBreakPriority bbPrio StringBuilder debugInfo = new StringBuilder(); - debugInfo.append( String.format( "&9### ** handleBlockBreakEvent ** ### " + + debugInfo.append( String.format( "### ** handleBlockBreakEvent ** ### " + "(event: BlockBreakEvent, config: %s, priority: %s, canceled: %s) ", bbPriority.name(), bbPriority.getBukkitEventPriority().name(), @@ -281,6 +296,8 @@ private void handleBlockBreakEvent( BlockBreakEvent e, BlockBreakPriority bbPrio debugInfo.append( eventResults.getDebugInfo() ); + + // Process all priorities if the event has not been canceled, and // process the MONITOR priority even if the event was canceled: if ( !bbPriority.isMonitor() && !e.isCancelled() || @@ -318,6 +335,22 @@ private void handleBlockBreakEvent( BlockBreakEvent e, BlockBreakPriority bbPrio return; } + + // Check for BlockConverters Event Triggers: + // If this function returns a true, then the event should be canceled so no other plugins + // process the block after the triggered plugin has processed it. + // If the eventTrigger is marked to remove block without drops, then the + // block break event priority will be set to MONITOR and will force the + // block to be removed by prison. + if ( checkBlockConverterEventTrigger( pmEvent, e ) ) { + + e.setCancelled( true ); + +// printDebugInfo( pmEvent, start ); +// return; + } + + // Validate the event. if ( !validateEvent( pmEvent ) ) { @@ -338,6 +371,14 @@ private void handleBlockBreakEvent( BlockBreakEvent e, BlockBreakPriority bbPrio else if ( pmEvent.getBbPriority().isMonitor() ) { // Stop here, and prevent additional processing. // Monitors should never process the event beyond this. + + // NOTE: BlockConverters EventTriggers will force processing to MONITOR + // plus require the block to be removed with no drops with + // no block events. + if ( pmEvent.isForceBlockRemoval() ) { + + finalizeBreakTheBlocks( pmEvent ); + } } @@ -460,16 +501,76 @@ else if ( cancelBy == EventListenerCancelBy.drops ) { // debugInfo.append( "(logic bypass) " ); // } + + boolean isPlayerAutosellEnabled = pmEvent.getSpigotPlayer().isAutoSellEnabled( pmEvent.getDebugInfo() ); + + +// // In the event, forceAutoSell is enabled, which means the drops must be sold. +// // The player's toggle cannot disable this. +// boolean forceAutoSell = isSellallEnabled && pmEvent.isForceAutoSell(); +// + +// // AutoFeature's autosell per block break - global setting +// boolean autoSellBySettings = +// isPlayerAutosellEnabled && +// isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled); + + + boolean isPlayerAutoSellByPerm = pmEvent.getSpigotPlayer().isAutoSellByPermEnabled( isPlayerAutosellEnabled ); + + + + + if ( isBoolean( AutoFeatures.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && + ( isPlayerAutosellEnabled || isPlayerAutoSellByPerm )) { + + pmEvent.getDebugInfo().append( Output.get().getColorCodeWarning()); + pmEvent.performSellAllOnPlayerInventoryLogged( "FORCED BlockBreakEvent sellall"); + pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug()); + } + + if ( isBoolean( AutoFeatures.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && + ( isPlayerAutosellEnabled || isPlayerAutoSellByPerm ) ) { + + if ( !getDelayedSellallPlayers().contains( pmEvent.getSpigotPlayer() ) ) { + + getDelayedSellallPlayers().add( pmEvent.getSpigotPlayer() ); + + int ticks = getInteger( AutoFeatures.isEnabledDelayedSellAllOnInventoryDelayInTicks ); + + pmEvent.getDebugInfo().append( Output.get().getColorCodeError()); + pmEvent.getDebugInfo().append( "(BlockBreakEvent delayed sellall submitted: no details available, see sellall debug info) " ); + pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug()); + + final PrisonMinesBlockBreakEvent pmEventFinal = pmEvent; + + new BukkitRunnable() { + @Override + public void run() { + + String message = pmEventFinal.performSellAllOnPlayerInventoryString("delayed sellall"); + getDelayedSellallPlayers().remove( pmEventFinal.getSpigotPlayer() ); + + Output.get().logDebug(message); + } + }.runTaskLater( SpigotPrison.getInstance(), ticks ); + } + } + + printDebugInfo( pmEvent, start ); } - - printDebugInfo( pmEvent, start ); + } + protected int checkBonusXp( Player player, Block block, ItemStack item ) { int bonusXp = 0; return bonusXp; } - + + public TreeSet getDelayedSellallPlayers() { + return delayedSellallPlayers; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java index 7d5b598e9..2a0c9ff00 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java @@ -13,6 +13,7 @@ import org.bukkit.plugin.PluginManager; import me.badbones69.crazyenchantments.api.events.BlastUseEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; @@ -56,8 +57,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -338,6 +341,13 @@ public void handleBlastUseEvent( BlastUseEvent e, BlockBreakPriority bbPriority } + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java index 799113caa..f3b5359fe 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java @@ -13,6 +13,7 @@ import org.bukkit.plugin.PluginManager; import me.pulsi_.prisonenchants.events.PEExplosionEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; @@ -48,8 +49,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } /** @@ -327,6 +330,13 @@ public void handlePEExplosionEvent( PEExplosionEvent e, BlockBreakPriority bbPri pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java index 64d5c0995..20680ca16 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java @@ -51,8 +51,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -321,8 +323,19 @@ protected void handleExplosiveBlockBreakEvent( ExplosiveBlockBreakEvent e, // than one. if ( e.getMineBomb() != null ) { pmEvent.setCalculateDurability( false ); + + // Set if forced autoSell: + pmEvent.setForceAutoSell( e.getMineBomb().isAutosell() ); } + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsExplosiveEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsExplosiveEvent.java index 982094061..595c9291a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsExplosiveEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsExplosiveEvent.java @@ -13,6 +13,7 @@ import org.bukkit.plugin.PluginManager; import me.revils.revenchants.events.ExplosiveEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; @@ -49,8 +50,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -238,7 +241,12 @@ public void dumpEventListeners( StringBuilder sb ) { // CrazyEnchants is not loaded... so ignore. } catch ( Exception e ) { - Output.get().logInfo( "AutoManager: RevEnchants ExplosiveEvent failed to load. [%s]", e.getMessage() ); + String causedBy = e.getCause() == null ? "" : e.getCause().getMessage(); + + Output.get().logInfo( "AutoManager: RevEnchants ExplosiveEvent failed to load. " + + "[%s] Caused by: [%s]", + e.getMessage(), + causedBy ); } } @@ -333,6 +341,14 @@ public void handleRevEnchantsExplosiveEvent( ExplosiveEvent e, BlockBreakPriorit } + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsJackHammerEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsJackHammerEvent.java index e5c1bc2ee..6af193697 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsJackHammerEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerRevEnchantsJackHammerEvent.java @@ -15,6 +15,7 @@ import org.bukkit.plugin.PluginManager; import me.revils.revenchants.events.JackHammerEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; @@ -54,8 +55,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -246,7 +249,12 @@ public void dumpEventListeners( StringBuilder sb ) { // CrazyEnchants is not loaded... so ignore. } catch ( Exception e ) { - Output.get().logInfo( "AutoManager: RevEnchants JackHammerEnchants failed to load. [%s]", e.getMessage() ); + String causedBy = e.getCause() == null ? "" : e.getCause().getMessage(); + + Output.get().logInfo( "AutoManager: RevEnchants JackHammerEnchants failed to load. " + + "[%s] Caused by: [%s]", + e.getMessage(), + causedBy, e.getMessage() ); } } @@ -359,6 +367,14 @@ public void handleRevEnchantsJackHammerEvent( JackHammerEvent e, BlockBreakPrior // pmEvent.getUnprocessedRawBlocks().add( blocks.get( i ) ); // } + + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + if ( !validateEvent( pmEvent ) ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java index 88240da24..5ea2ff076 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java @@ -14,6 +14,7 @@ import com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; @@ -53,7 +54,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -391,6 +395,16 @@ public void handleTEBlockExplodeEvent( TEBlockExplodeEvent e, BlockBreakPriority pmEvent.setUnprocessedRawBlocks( e.blockList() ); + + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonExplosionTriggerEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonExplosionTriggerEvent.java new file mode 100644 index 000000000..758d082b0 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonExplosionTriggerEvent.java @@ -0,0 +1,442 @@ +package tech.mcprison.prison.spigot.autofeatures.events; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.PluginManager; + +import dev.drawethree.xprison.enchants.api.events.ExplosionTriggerEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.block.BlockBreakPriority; + +public class AutoManagerXPrisonExplosionTriggerEvent + extends AutoManagerFeatures + implements PrisonEventManager +{ + + +// private ExplosionTriggerEvent ete; +// private LayerTriggerEvent lte; +// private NukeTriggerEvent nte; + +// dev.drawethree.xprison.enchants.api.events.ExplosionTriggerEvent; + + + + private BlockBreakPriority bbPriority; + + public AutoManagerXPrisonExplosionTriggerEvent() { + super(); + } + + public AutoManagerXPrisonExplosionTriggerEvent( BlockBreakPriority bbPriority ) { + super(); + + this.bbPriority = bbPriority; + } + + + public BlockBreakPriority getBbPriority() { + return bbPriority; + } + public void setBbPriority( BlockBreakPriority bbPriority ) { + this.bbPriority = bbPriority; + } + + @Override + public void registerEvents() { + + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } + } + + + public class AutoManagerXPrisonExplosionTriggerEventListener + extends AutoManagerXPrisonExplosionTriggerEvent + implements Listener { + + public AutoManagerXPrisonExplosionTriggerEventListener( BlockBreakPriority bbPriority ) { + super( bbPriority ); + } + + @EventHandler(priority=EventPriority.NORMAL) + public void onXPrisonExplosionTriggerEvent( + ExplosionTriggerEvent e, BlockBreakPriority bbPriority) { + + if ( isDisabled( e.getPlayer().getLocation().getWorld().getName() ) || + bbPriority.isDisabled() ) { + return; + } + + handleXPrisonExplosionTriggerEvent( e, bbPriority ); + } + } + + + @Override + public void initialize() { + + String eP = getMessage( AutoFeatures.XPrisonExplosionTriggerEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + setBbPriority( bbPriority ); + +// boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( getBbPriority() == BlockBreakPriority.DISABLED ) { + return; + } + + // Check to see if the class ExplosionTriggerEvent even exists: + try { + Output.get().logInfo( "AutoManager: checking if loaded: XPrison ExplosionTriggerEvent" ); + + Class.forName( "dev.drawethree.xprison.enchants.api.events.ExplosionTriggerEvent", false, + this.getClass().getClassLoader() ); + + Output.get().logInfo( "AutoManager: Trying to register XPrison ExplosionTriggerEvent" ); + + if ( getBbPriority() != BlockBreakPriority.DISABLED ) { + if ( bbPriority.isComponentCompound() ) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener( subBBPriority ); + } + } + else { + + createListener(bbPriority); + } + + } + } + catch ( ClassNotFoundException e ) { + // CrazyEnchants is not loaded... so ignore. + Output.get().logInfo( "AutoManager: XPrison ExplosionTriggerEvent is not loaded" ); + } + catch ( Exception e ) { + Output.get().logInfo( "AutoManager: XPrison ExplosionTriggerEvent failed to load. [%s]", e.getMessage() ); + } + } + + private void createListener( BlockBreakPriority bbPriority ) { + + SpigotPrison prison = SpigotPrison.getInstance(); + PluginManager pm = Bukkit.getServer().getPluginManager(); + EventPriority ePriority = bbPriority.getBukkitEventPriority(); + + + AutoManagerXPrisonExplosionTriggerEventListener autoManagerListener = + new AutoManagerXPrisonExplosionTriggerEventListener( bbPriority ); + + pm.registerEvent( + ExplosionTriggerEvent.class, + autoManagerListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + + ExplosionTriggerEvent exEvent = (ExplosionTriggerEvent) e; + + ((AutoManagerXPrisonExplosionTriggerEventListener)l) + .onXPrisonExplosionTriggerEvent(exEvent, bbPriority); + } + }, + prison); + prison.getRegisteredBlockListeners().add( autoManagerListener ); + } + + + @Override + public void unregisterListeners() { + +// super.unregisterListeners(); + } + + @Override + public void dumpEventListeners() { + + StringBuilder sb = new StringBuilder(); + + dumpEventListeners( sb ); + + if ( sb.length() > 0 ) { + + + for ( String line : sb.toString().split( "\n" ) ) { + + Output.get().logInfo( line ); + } + } + + } + + + @Override + public void dumpEventListeners( StringBuilder sb ) { + + String eP = getMessage( AutoFeatures.XPrisonExplosionTriggerEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( !isEventEnabled ) { + return; + } + + // Check to see if the class ExplosionTriggerEvent even exists: + try { + + Class.forName( "dev.drawethree.xprison.enchants.api.events.ExplosionTriggerEvent", false, + this.getClass().getClassLoader() ); + + + HandlerList handlers = ExplosionTriggerEvent.getHandlerList(); + +// String eP = getMessage( AutoFeatures.blockBreakEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + dumpEventListenersCore( "XPrison ExplosionTriggerEvent", handlers, bbPriority, sb ); + + +// +// BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); +// +// +// String title = String.format( +// "ExplosionTriggerEvent (%s)", +// ( bbPriority == null ? "--none--" : bbPriority.name()) ); +// +// ChatDisplay eventDisplay = Prison.get().getPlatform().dumpEventListenersChatDisplay( +// title, +// new SpigotHandlerList( ExplosionTriggerEvent.getHandlerList()) ); +// +// if ( eventDisplay != null ) { +// sb.append( eventDisplay.toStringBuilder() ); +// sb.append( "\n" ); +// } +// +// +// if ( bbPriority.isComponentCompound() ) { +// StringBuilder sbCP = new StringBuilder(); +// for ( BlockBreakPriority bbp : bbPriority.getComponentPriorities() ) { +// if ( sbCP.length() > 0 ) { +// sbCP.append( ", " ); +// } +// sbCP.append( "'" ).append( bbp.name() ).append( "'" ); +// } +// +// String msg = String.format( "Note '%s' is a compound of: [%s]", +// bbPriority.name(), +// sbCP ); +// +// sb.append( msg ).append( "\n" ); +// } + } + catch ( ClassNotFoundException e ) { + // XPrison is not loaded... so ignore. + } + catch ( Exception e ) { + String causedBy = e.getCause() == null ? "" : e.getCause().getMessage(); + + Output.get().logInfo( "AutoManager: XPrison ExplosionTriggerEvent failed to load. " + + "[%s] Caused by: [%s]", + e.getMessage(), + causedBy ); + } + } + + + /** + *

Since there are multiple blocks associated with this event, pull out the player first and + * get the mine, then loop through those blocks to make sure they are within the mine. + *

+ * + *

The logic in this function is slightly different compared to genericBlockEvent() because this + * event contains multiple blocks so it's far more efficient to process the player data once. + * So that basically needed a slight refactoring. + *

+ * + * @param e + */ + public void handleXPrisonExplosionTriggerEvent( ExplosionTriggerEvent e, BlockBreakPriority bbPriority ) { + + PrisonMinesBlockBreakEvent pmEvent = null; + long start = System.nanoTime(); + + // If the event is canceled, it still needs to be processed because of the + // MONITOR events: + // An event will be "canceled" and "ignored" if the block + // BlockUtils.isUnbreakable(), or if the mine is actively resetting. + // The event will also be ignored if the block is outside of a mine + // or if the targetBlock has been set to ignore all block events which + // means the block has already been processed. + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + e.getPlayer(), e.getOriginBlock(), + bbPriority, true ); + + if ( eventResults.isIgnoreEvent() ) { + return; + } + + + StringBuilder debugInfo = new StringBuilder(); + + debugInfo.append( String.format( "### ** handleXPrisonExplosionTriggerEvent ** ### " + + "(event: ExplosionTriggerEvent, config: %s, priority: %s, canceled: %s) ", + bbPriority.name(), + bbPriority.getBukkitEventPriority().name(), + (e.isCancelled() ? "TRUE " : "FALSE") + ) ); + + debugInfo.append( eventResults.getDebugInfo() ); + + + // NOTE that check for auto manager has happened prior to accessing this function. + + // Process all priorities if the event has not been canceled, and + // process the MONITOR priority even if the event was canceled: + if ( !bbPriority.isMonitor() && !e.isCancelled() || + bbPriority.isMonitor() && + e.getBlocksAffected().size() > 0 ) { + + + +// Block bukkitBlock = e.getBlocks().get( 0 ); + + BlockEventType eventType = BlockEventType.XPrisonExplosionTriggerEvent; + String triggered = null; + + + pmEvent = new PrisonMinesBlockBreakEvent( + eventResults, +// bukkitBlock, +// e.getPlayer(), +// eventResults.getMine(), +// bbPriority, + eventType, triggered, + debugInfo ); + + + // NOTE: Check for the ACCESS priority and if someone does not have access, then return + // with a cancel on the event. Both ACCESSBLOCKEVENTS and ACCESSMONITOR will be + // converted to just ACCESS at this point, and the other part will run under either + // BLOCKEVENTS or MONITOR. + // This check has to be performed after creating the pmEvent object since it uses + // a lot of the internal variables and objects. There is not much of an impact since + // the validateEvent() has not been ran yet. + if ( checkIfNoAccess( pmEvent, start ) ) { + + e.setCancelled( true ); + return; + } + + + for ( int i = 0; i < e.getBlocksAffected().size(); i++ ) { + pmEvent.getUnprocessedRawBlocks().add( e.getBlocksAffected().get( i ) ); + } + + + + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + + if ( !validateEvent( pmEvent ) ) { + + // The event has not passed validation. All logging and Errors have been recorded + // so do nothing more. This is to just prevent normal processing from occurring. + + if ( pmEvent.isCancelOriginalEvent() ) { + + e.setCancelled( true ); + } + + debugInfo.append( "(doAction failed validation) " ); + } + + + + // The validation was successful, but stop processing for the MONITOR priorities. + // Note that BLOCKEVENTS processing occurred already within validateEvent(): + else if ( pmEvent.getBbPriority().isMonitor() ) { + // Stop here, and prevent additional processing. + // Monitors should never process the event beyond this. + } + + + + // This is where the processing actually happens: + else { + +// debugInfo.append( "(normal processing initiating) " ); + + // check all external events such as mcMMO and EZBlocks: +// if ( e instanceof BlockBreakEvent ) { +// processPMBBExternalEvents( pmEvent, debugInfo, e ); +// } +// + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + if ( cancelBy != EventListenerCancelBy.none ) { + + e.setCancelled( true ); + debugInfo.append( "(event canceled) " ); + } +// else if ( cancelBy == EventListenerCancelBy.drops ) { +// try +// { +// e.setDropItems( false ); +// debugInfo.append( "(drop canceled) " ); +// } +// catch ( NoSuchMethodError e1 ) +// { +// String message = String.format( +// "Warning: The autoFeaturesConfig.yml setting `cancelAllBlockEventBlockDrops` " + +// "is not valid for this version of Spigot. It's only vaid for spigot v1.12.x and higher. " + +// "Modify the config settings and set this value to `false`. For now, it is temporarily " + +// "disabled. [%s]", +// e1.getMessage() ); +// Output.get().logWarn( message ); +// +// AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() +// .setFeature( AutoFeatures.cancelAllBlockEventBlockDrops, false ); +// } +// +// } + } + + + } + + printDebugInfo( pmEvent, start ); + } + + @Override + protected int checkBonusXp( Player player, Block block, ItemStack item ) { + int bonusXp = 0; + + return bonusXp; + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonLayerTriggerEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonLayerTriggerEvent.java new file mode 100644 index 000000000..6043f5a2b --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonLayerTriggerEvent.java @@ -0,0 +1,443 @@ +package tech.mcprison.prison.spigot.autofeatures.events; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.PluginManager; + +import dev.drawethree.xprison.enchants.api.events.LayerTriggerEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.block.BlockBreakPriority; + +public class AutoManagerXPrisonLayerTriggerEvent + extends AutoManagerFeatures + implements PrisonEventManager +{ + + +// private ExplosionTriggerEvent ete; +// private LayerTriggerEvent lte; +// private NukeTriggerEvent nte; + + //dev.drawethree.xprison.enchants.api.events.LayerTriggerEvent; + + + + private BlockBreakPriority bbPriority; + + public AutoManagerXPrisonLayerTriggerEvent() { + super(); + } + + public AutoManagerXPrisonLayerTriggerEvent( BlockBreakPriority bbPriority ) { + super(); + + this.bbPriority = bbPriority; + } + + + public BlockBreakPriority getBbPriority() { + return bbPriority; + } + public void setBbPriority( BlockBreakPriority bbPriority ) { + this.bbPriority = bbPriority; + } + + @Override + public void registerEvents() { + + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } + } + + + public class AutoManagerXPrisonLayerTriggerEventListener + extends AutoManagerXPrisonLayerTriggerEvent + implements Listener { + + public AutoManagerXPrisonLayerTriggerEventListener( BlockBreakPriority bbPriority ) { + super( bbPriority ); + } + + @EventHandler(priority=EventPriority.NORMAL) + public void onXPrisonLayerTriggerEvent( + LayerTriggerEvent e, BlockBreakPriority bbPriority) { + + if ( isDisabled( e.getPlayer().getLocation().getWorld().getName() ) || + bbPriority.isDisabled() ) { + return; + } + + handleXPrisonLayerTriggerEvent( e, bbPriority ); + } + } + + + @Override + public void initialize() { + + String eP = getMessage( AutoFeatures.XPrisonLayerTriggerEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + setBbPriority( bbPriority ); + + // boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( getBbPriority() == BlockBreakPriority.DISABLED ) { + return; + } + + // Check to see if the class LayerTriggerEvent even exists: + try { + Output.get().logInfo( "AutoManager: checking if loaded: XPrison LayerTriggerEvent" ); + + Class.forName( "dev.drawethree.xprison.enchants.api.events.LayerTriggerEvent", false, + this.getClass().getClassLoader() ); + + Output.get().logInfo( "AutoManager: Trying to register XPrison LayerTriggerEvent" ); + + if ( getBbPriority() != BlockBreakPriority.DISABLED ) { + if ( bbPriority.isComponentCompound() ) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener( subBBPriority ); + } + } + else { + + createListener(bbPriority); + } + + } + } + catch ( ClassNotFoundException e ) { + // CrazyEnchants is not loaded... so ignore. + Output.get().logInfo( "AutoManager: XPrison LayerTriggerEvent is not loaded" ); + } + catch ( Exception e ) { + Output.get().logInfo( "AutoManager: XPrison LayerTriggerEvent failed to load. [%s]", e.getMessage() ); + } + } + + private void createListener( BlockBreakPriority bbPriority ) { + + SpigotPrison prison = SpigotPrison.getInstance(); + PluginManager pm = Bukkit.getServer().getPluginManager(); + EventPriority ePriority = bbPriority.getBukkitEventPriority(); + + + AutoManagerXPrisonLayerTriggerEventListener autoManagerListener = + new AutoManagerXPrisonLayerTriggerEventListener( bbPriority ); + + pm.registerEvent( + LayerTriggerEvent.class, + autoManagerListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + + LayerTriggerEvent exEvent = (LayerTriggerEvent) e; + + ((AutoManagerXPrisonLayerTriggerEventListener)l) + .onXPrisonLayerTriggerEvent(exEvent, bbPriority); + } + }, + prison); + prison.getRegisteredBlockListeners().add( autoManagerListener ); + } + + + @Override + public void unregisterListeners() { + + // super.unregisterListeners(); + } + + @Override + public void dumpEventListeners() { + + StringBuilder sb = new StringBuilder(); + + dumpEventListeners( sb ); + + if ( sb.length() > 0 ) { + + + for ( String line : sb.toString().split( "\n" ) ) { + + Output.get().logInfo( line ); + } + } + + } + + +@Override +public void dumpEventListeners( StringBuilder sb ) { + + String eP = getMessage( AutoFeatures.XPrisonLayerTriggerEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( !isEventEnabled ) { + return; + } + + // Check to see if the class LayerTriggerEvent even exists: + try { + + Class.forName( "dev.drawethree.xprison.enchants.api.events.LayerTriggerEvent", false, + this.getClass().getClassLoader() ); + + + HandlerList handlers = LayerTriggerEvent.getHandlerList(); + +// String eP = getMessage( AutoFeatures.blockBreakEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + dumpEventListenersCore( "XPrison LayerTriggerEvent", handlers, bbPriority, sb ); + + +// +// BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); +// +// +// String title = String.format( +// "LayerTriggerEvent (%s)", +// ( bbPriority == null ? "--none--" : bbPriority.name()) ); +// +// ChatDisplay eventDisplay = Prison.get().getPlatform().dumpEventListenersChatDisplay( +// title, +// new SpigotHandlerList( LayerTriggerEvent.getHandlerList()) ); +// +// if ( eventDisplay != null ) { +// sb.append( eventDisplay.toStringBuilder() ); +// sb.append( "\n" ); +// } +// +// +// if ( bbPriority.isComponentCompound() ) { +// StringBuilder sbCP = new StringBuilder(); +// for ( BlockBreakPriority bbp : bbPriority.getComponentPriorities() ) { +// if ( sbCP.length() > 0 ) { +// sbCP.append( ", " ); +// } +// sbCP.append( "'" ).append( bbp.name() ).append( "'" ); +// } +// +// String msg = String.format( "Note '%s' is a compound of: [%s]", +// bbPriority.name(), +// sbCP ); +// +// sb.append( msg ).append( "\n" ); +// } + } + catch ( ClassNotFoundException e ) { + // XPrison is not loaded... so ignore. + } + catch ( Exception e ) { + String causedBy = e.getCause() == null ? "" : e.getCause().getMessage(); + + Output.get().logInfo( "AutoManager: XPrison LayerTriggerEvent failed to load. " + + "[%s] Caused by: [%s]", + e.getMessage(), + causedBy ); + } +} + + +/** + *

Since there are multiple blocks associated with this event, pull out the player first and + * get the mine, then loop through those blocks to make sure they are within the mine. + *

+ * + *

The logic in this function is slightly different compared to genericBlockEvent() because this + * event contains multiple blocks so it's far more efficient to process the player data once. + * So that basically needed a slight refactoring. + *

+ * + * @param e + */ +public void handleXPrisonLayerTriggerEvent( LayerTriggerEvent e, BlockBreakPriority bbPriority ) { + + PrisonMinesBlockBreakEvent pmEvent = null; + long start = System.nanoTime(); + + // If the event is canceled, it still needs to be processed because of the + // MONITOR events: + // An event will be "canceled" and "ignored" if the block + // BlockUtils.isUnbreakable(), or if the mine is actively resetting. + // The event will also be ignored if the block is outside of a mine + // or if the targetBlock has been set to ignore all block events which + // means the block has already been processed. + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + e.getPlayer(), e.getOriginBlock(), + bbPriority, true ); + + if ( eventResults.isIgnoreEvent() ) { + return; + } + + + StringBuilder debugInfo = new StringBuilder(); + + debugInfo.append( String.format( "### ** handleXPrisonLayerTriggerEvent ** ### " + + "(event: LayerTriggerEvent, config: %s, priority: %s, canceled: %s) ", + bbPriority.name(), + bbPriority.getBukkitEventPriority().name(), + (e.isCancelled() ? "TRUE " : "FALSE") + ) ); + + debugInfo.append( eventResults.getDebugInfo() ); + + + // NOTE that check for auto manager has happened prior to accessing this function. + + // Process all priorities if the event has not been canceled, and + // process the MONITOR priority even if the event was canceled: + if ( !bbPriority.isMonitor() && !e.isCancelled() || + bbPriority.isMonitor() && + e.getBlocksAffected().size() > 0 ) { + + + +// Block bukkitBlock = e.getBlocks().get( 0 ); + + BlockEventType eventType = BlockEventType.XPrisonLayerTriggerEvent; + String triggered = null; + + + pmEvent = new PrisonMinesBlockBreakEvent( + eventResults, +// bukkitBlock, +// e.getPlayer(), +// eventResults.getMine(), +// bbPriority, + eventType, triggered, + debugInfo ); + + + // NOTE: Check for the ACCESS priority and if someone does not have access, then return + // with a cancel on the event. Both ACCESSBLOCKEVENTS and ACCESSMONITOR will be + // converted to just ACCESS at this point, and the other part will run under either + // BLOCKEVENTS or MONITOR. + // This check has to be performed after creating the pmEvent object since it uses + // a lot of the internal variables and objects. There is not much of an impact since + // the validateEvent() has not been ran yet. + if ( checkIfNoAccess( pmEvent, start ) ) { + + e.setCancelled( true ); + return; + } + + + for ( int i = 0; i < e.getBlocksAffected().size(); i++ ) { + pmEvent.getUnprocessedRawBlocks().add( e.getBlocksAffected().get( i ) ); + } + + + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + + if ( !validateEvent( pmEvent ) ) { + + // The event has not passed validation. All logging and Errors have been recorded + // so do nothing more. This is to just prevent normal processing from occurring. + + if ( pmEvent.isCancelOriginalEvent() ) { + + e.setCancelled( true ); + } + + pmEvent.setDebugColorCodeWarning(); + debugInfo.append( "(doAction failed validation) " ); + pmEvent.setDebugColorCodeDebug(); + } + + + + // The validation was successful, but stop processing for the MONITOR priorities. + // Note that BLOCKEVENTS processing occurred already within validateEvent(): + else if ( pmEvent.getBbPriority().isMonitor() ) { + // Stop here, and prevent additional processing. + // Monitors should never process the event beyond this. + } + + + + // This is where the processing actually happens: + else { + +// debugInfo.append( "(normal processing initiating) " ); + + // check all external events such as mcMMO and EZBlocks: +// if ( e instanceof BlockBreakEvent ) { +// processPMBBExternalEvents( pmEvent, debugInfo, e ); +// } +// + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + if ( cancelBy != EventListenerCancelBy.none ) { + + e.setCancelled( true ); + debugInfo.append( "(event canceled) " ); + } +// else if ( cancelBy == EventListenerCancelBy.drops ) { +// try +// { +// e.setDropItems( false ); +// debugInfo.append( "(drop canceled) " ); +// } +// catch ( NoSuchMethodError e1 ) +// { +// String message = String.format( +// "Warning: The autoFeaturesConfig.yml setting `cancelAllBlockEventBlockDrops` " + +// "is not valid for this version of Spigot. It's only vaid for spigot v1.12.x and higher. " + +// "Modify the config settings and set this value to `false`. For now, it is temporarily " + +// "disabled. [%s]", +// e1.getMessage() ); +// Output.get().logWarn( message ); +// +// AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() +// .setFeature( AutoFeatures.cancelAllBlockEventBlockDrops, false ); +// } +// +// } + } + + + } + + printDebugInfo( pmEvent, start ); +} + + @Override + protected int checkBonusXp( Player player, Block block, ItemStack item ) { + int bonusXp = 0; + + return bonusXp; + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonNukeTriggerEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonNukeTriggerEvent.java new file mode 100644 index 000000000..2185fc3d5 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerXPrisonNukeTriggerEvent.java @@ -0,0 +1,443 @@ +package tech.mcprison.prison.spigot.autofeatures.events; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.PluginManager; + +import dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.block.BlockBreakPriority; + +public class AutoManagerXPrisonNukeTriggerEvent + extends AutoManagerFeatures + implements PrisonEventManager +{ + + +// private ExplosionTriggerEvent ete; +// private LayerTriggerEvent lte; +// private NukeTriggerEvent nte; + + //dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent; + + + + private BlockBreakPriority bbPriority; + + public AutoManagerXPrisonNukeTriggerEvent() { + super(); + } + + public AutoManagerXPrisonNukeTriggerEvent( BlockBreakPriority bbPriority ) { + super(); + + this.bbPriority = bbPriority; + } + + + public BlockBreakPriority getBbPriority() { + return bbPriority; + } + public void setBbPriority( BlockBreakPriority bbPriority ) { + this.bbPriority = bbPriority; + } + + @Override + public void registerEvents() { + + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } + } + + +public class AutoManagerXPrisonNukeTriggerEventListener + extends AutoManagerXPrisonNukeTriggerEvent + implements Listener { + + public AutoManagerXPrisonNukeTriggerEventListener( BlockBreakPriority bbPriority ) { + super( bbPriority ); + } + + @EventHandler(priority=EventPriority.NORMAL) + public void onXPrisonNukeTriggerEvent( + NukeTriggerEvent e, BlockBreakPriority bbPriority) { + + if ( isDisabled( e.getPlayer().getLocation().getWorld().getName() ) || + bbPriority.isDisabled() ) { + return; + } + + handleXPrisonNukeTriggerEvent( e, bbPriority ); + } +} + + +@Override +public void initialize() { + + String eP = getMessage( AutoFeatures.XPrisonNukeTriggerEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + setBbPriority( bbPriority ); + +// boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( getBbPriority() == BlockBreakPriority.DISABLED ) { + return; + } + + // Check to see if the class NukeTriggerEvent even exists: + try { + Output.get().logInfo( "AutoManager: checking if loaded: XPrison NukeTriggerEvent" ); + + Class.forName( "dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent", false, + this.getClass().getClassLoader() ); + + Output.get().logInfo( "AutoManager: Trying to register XPrison NukeTriggerEvent" ); + + if ( getBbPriority() != BlockBreakPriority.DISABLED ) { + if ( bbPriority.isComponentCompound() ) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener( subBBPriority ); + } + } + else { + + createListener(bbPriority); + } + + } + } + catch ( ClassNotFoundException e ) { + // CrazyEnchants is not loaded... so ignore. + Output.get().logInfo( "AutoManager: XPrison NukeTriggerEvent is not loaded" ); + } + catch ( Exception e ) { + Output.get().logInfo( "AutoManager: XPrison NukeTriggerEvent failed to load. [%s]", e.getMessage() ); + } +} + +private void createListener( BlockBreakPriority bbPriority ) { + + SpigotPrison prison = SpigotPrison.getInstance(); + PluginManager pm = Bukkit.getServer().getPluginManager(); + EventPriority ePriority = bbPriority.getBukkitEventPriority(); + + + AutoManagerXPrisonNukeTriggerEventListener autoManagerListener = + new AutoManagerXPrisonNukeTriggerEventListener( bbPriority ); + + pm.registerEvent( + NukeTriggerEvent.class, + autoManagerListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + + NukeTriggerEvent exEvent = (NukeTriggerEvent) e; + + ((AutoManagerXPrisonNukeTriggerEventListener)l) + .onXPrisonNukeTriggerEvent(exEvent, bbPriority); + } + }, + prison); + prison.getRegisteredBlockListeners().add( autoManagerListener ); +} + + +@Override +public void unregisterListeners() { + +// super.unregisterListeners(); +} + +@Override +public void dumpEventListeners() { + + StringBuilder sb = new StringBuilder(); + + dumpEventListeners( sb ); + + if ( sb.length() > 0 ) { + + + for ( String line : sb.toString().split( "\n" ) ) { + + Output.get().logInfo( line ); + } + } + +} + + +@Override +public void dumpEventListeners( StringBuilder sb ) { + + String eP = getMessage( AutoFeatures.XPrisonNukeTriggerEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( !isEventEnabled ) { + return; + } + + // Check to see if the class NukeTriggerEvent even exists: + try { + + Class.forName( "dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent", false, + this.getClass().getClassLoader() ); + + + HandlerList handlers = NukeTriggerEvent.getHandlerList(); + +// String eP = getMessage( AutoFeatures.blockBreakEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + dumpEventListenersCore( "XPrison NukeTriggerEvent", handlers, bbPriority, sb ); + + +// +// BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); +// +// +// String title = String.format( +// "NukeTriggerEvent (%s)", +// ( bbPriority == null ? "--none--" : bbPriority.name()) ); +// +// ChatDisplay eventDisplay = Prison.get().getPlatform().dumpEventListenersChatDisplay( +// title, +// new SpigotHandlerList( NukeTriggerEvent.getHandlerList()) ); +// +// if ( eventDisplay != null ) { +// sb.append( eventDisplay.toStringBuilder() ); +// sb.append( "\n" ); +// } +// +// +// if ( bbPriority.isComponentCompound() ) { +// StringBuilder sbCP = new StringBuilder(); +// for ( BlockBreakPriority bbp : bbPriority.getComponentPriorities() ) { +// if ( sbCP.length() > 0 ) { +// sbCP.append( ", " ); +// } +// sbCP.append( "'" ).append( bbp.name() ).append( "'" ); +// } +// +// String msg = String.format( "Note '%s' is a compound of: [%s]", +// bbPriority.name(), +// sbCP ); +// +// sb.append( msg ).append( "\n" ); +// } + } + catch ( ClassNotFoundException e ) { + // XPrison is not loaded... so ignore. + } + catch ( Exception e ) { + String causedBy = e.getCause() == null ? "" : e.getCause().getMessage(); + + Output.get().logInfo( "AutoManager: XPrison NukeTriggerEvent failed to load. " + + "[%s] Caused by: [%s]", + e.getMessage(), + causedBy ); + } +} + + +/** + *

Since there are multiple blocks associated with this event, pull out the player first and + * get the mine, then loop through those blocks to make sure they are within the mine. + *

+ * + *

The logic in this function is slightly different compared to genericBlockEvent() because this + * event contains multiple blocks so it's far more efficient to process the player data once. + * So that basically needed a slight refactoring. + *

+ * + * @param e + */ +public void handleXPrisonNukeTriggerEvent( NukeTriggerEvent e, BlockBreakPriority bbPriority ) { + + PrisonMinesBlockBreakEvent pmEvent = null; + long start = System.nanoTime(); + + // If the event is canceled, it still needs to be processed because of the + // MONITOR events: + // An event will be "canceled" and "ignored" if the block + // BlockUtils.isUnbreakable(), or if the mine is actively resetting. + // The event will also be ignored if the block is outside of a mine + // or if the targetBlock has been set to ignore all block events which + // means the block has already been processed. + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + e.getPlayer(), e.getOriginBlock(), + bbPriority, true ); + + if ( eventResults.isIgnoreEvent() ) { + return; + } + + + StringBuilder debugInfo = new StringBuilder(); + + debugInfo.append( String.format( "### ** handleXPrisonNukeTriggerEvent ** ### " + + "(event: NukeTriggerEvent, config: %s, priority: %s, canceled: %s) ", + bbPriority.name(), + bbPriority.getBukkitEventPriority().name(), + (e.isCancelled() ? "TRUE " : "FALSE") + ) ); + + debugInfo.append( eventResults.getDebugInfo() ); + + + // NOTE that check for auto manager has happened prior to accessing this function. + + // Process all priorities if the event has not been canceled, and + // process the MONITOR priority even if the event was canceled: + if ( !bbPriority.isMonitor() && !e.isCancelled() || + bbPriority.isMonitor() && + e.getBlocksAffected().size() > 0 ) { + + + +// Block bukkitBlock = e.getBlocks().get( 0 ); + + BlockEventType eventType = BlockEventType.XPrisonNukeTriggerEvent; + String triggered = null; + + + pmEvent = new PrisonMinesBlockBreakEvent( + eventResults, +// bukkitBlock, +// e.getPlayer(), +// eventResults.getMine(), +// bbPriority, + eventType, triggered, + debugInfo ); + + + // NOTE: Check for the ACCESS priority and if someone does not have access, then return + // with a cancel on the event. Both ACCESSBLOCKEVENTS and ACCESSMONITOR will be + // converted to just ACCESS at this point, and the other part will run under either + // BLOCKEVENTS or MONITOR. + // This check has to be performed after creating the pmEvent object since it uses + // a lot of the internal variables and objects. There is not much of an impact since + // the validateEvent() has not been ran yet. + if ( checkIfNoAccess( pmEvent, start ) ) { + + e.setCancelled( true ); + return; + } + + + for ( int i = 0; i < e.getBlocksAffected().size(); i++ ) { + pmEvent.getUnprocessedRawBlocks().add( e.getBlocksAffected().get( i ) ); + } + + + + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + + + if ( !validateEvent( pmEvent ) ) { + + // The event has not passed validation. All logging and Errors have been recorded + // so do nothing more. This is to just prevent normal processing from occurring. + + if ( pmEvent.isCancelOriginalEvent() ) { + + e.setCancelled( true ); + } + + debugInfo.append( "(doAction failed validation) " ); + } + + + + // The validation was successful, but stop processing for the MONITOR priorities. + // Note that BLOCKEVENTS processing occurred already within validateEvent(): + else if ( pmEvent.getBbPriority().isMonitor() ) { + // Stop here, and prevent additional processing. + // Monitors should never process the event beyond this. + } + + + + // This is where the processing actually happens: + else { + +// debugInfo.append( "(normal processing initiating) " ); + + // check all external events such as mcMMO and EZBlocks: +// if ( e instanceof BlockBreakEvent ) { +// processPMBBExternalEvents( pmEvent, debugInfo, e ); +// } +// + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + if ( cancelBy != EventListenerCancelBy.none ) { + + e.setCancelled( true ); + debugInfo.append( "(event canceled) " ); + } +// else if ( cancelBy == EventListenerCancelBy.drops ) { +// try +// { +// e.setDropItems( false ); +// debugInfo.append( "(drop canceled) " ); +// } +// catch ( NoSuchMethodError e1 ) +// { +// String message = String.format( +// "Warning: The autoFeaturesConfig.yml setting `cancelAllBlockEventBlockDrops` " + +// "is not valid for this version of Spigot. It's only vaid for spigot v1.12.x and higher. " + +// "Modify the config settings and set this value to `false`. For now, it is temporarily " + +// "disabled. [%s]", +// e1.getMessage() ); +// Output.get().logWarn( message ); +// +// AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() +// .setFeature( AutoFeatures.cancelAllBlockEventBlockDrops, false ); +// } +// +// } + } + + + } + + printDebugInfo( pmEvent, start ); +} + + @Override + protected int checkBonusXp( Player player, Block block, ItemStack item ) { + int bonusXp = 0; + + return bonusXp; + } +} \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java index 15745d535..23bfb8643 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java @@ -50,8 +50,10 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { @Override public void registerEvents() { - initialize(); - + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + initialize(); + } } @@ -326,6 +328,14 @@ private void handleZenchantmentsBlockBreakEvent( BlockBreakEvent e, BlockBreakPr } + + // Check to see if the blockConverter's EventTrigger should have + // it's blocks suppressed from explosion events. If they should be + // removed, then it's removed within this funciton. + removeEventTriggerBlocksFromExplosions( pmEvent ); + + + if ( !validateEvent( pmEvent ) ) { // The event has not passed validation. All logging and Errors have been recorded diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java index 27981860d..0ddd9ffd0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.autofeatures.events; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -27,21 +28,41 @@ public class PrisonDebugBlockInspector // extends OnBlockBreakMines { + private static PrisonDebugBlockInspector instance; + private OnBlockBreakMines obbMines; + private long lastAccess = 0; +// private boolean active = false; + public enum EventDropsStatus { normal, canceled, notSupported; } - public PrisonDebugBlockInspector() { + private PrisonDebugBlockInspector() { super(); obbMines = new OnBlockBreakMines(); + + init(); } + + public static PrisonDebugBlockInspector getInstance() { + if ( instance == null ) { + synchronized ( PrisonDebugBlockInspector.class ) { + if ( instance == null ) { - public void init() { + instance = new PrisonDebugBlockInspector(); + + } + } + } + return instance; + } + + private void init() { Prison.get().getEventBus().register(this); @@ -81,6 +102,15 @@ public void init() { @Subscribe public void onPlayerInteract( PrisonPlayerInteractEvent e ) { + List output = new ArrayList<>(); + + + // Cool down: run no sooner than every 2 seconds... prevents duplicate runs: + if ( lastAccess != 0 && (System.currentTimeMillis() - lastAccess) < 2000 ) { + return; + } + + this.lastAccess = System.currentTimeMillis(); ItemStack ourItem = e.getItemInHand(); ItemStack toolItem = SelectionManager.SELECTION_TOOL; @@ -107,9 +137,9 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { if ( mine == null ) { - player.sendMessage( + output.add( String.format( - "&dDebugBlockInfo: &7Not in a mine. &5%s &7%s", + "-&dDebugBlockInfo: &7Not in a mine. &5%s &7%s", sBlock.getBlockName(), location.toWorldCoordinates()) ); } @@ -125,56 +155,63 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { // checkForCustomBlock( sBlock, targetBlock ); String m1 = String.format( - "&dDebugBlockInfo: &3Mine &7%s &3Rank: &7%s " + - "&5%s &7%s", + "-&dDebugBlockInfo: &3Mine &7%s &3Rank: &7%s " + + "&5%s &7%s ", mine.getName(), (mine.getRank() == null ? "---" : mine.getRank().getName()), sBlock.getBlockName(), location.toWorldCoordinates()); - player.sendMessage( m1 ); - Output.get().logInfo( m1 ); + output.add( m1 ); +// player.sendMessage( m1 ); +// Output.get().logInfo( m1 ); // Get the mine's targetBlock: // MineTargetPrisonBlock tBlock = mine.getTargetPrisonBlock( sBlock ); if ( targetBlock == null ) { - player.sendMessage( "Notice: Unable to get a mine's targetBlock. This could imply " + + + + output.add( "-Notice: Unable to get a mine's targetBlock. This could imply " + "that the mine was not reset since the server started up, or that the air-block " + "check was not ran yet. Use `/mine reset " + mine.getName() + "' to reset the " + "target blocks." ); } else { - String message = String.format( " &3TargetBlock: &7%s " + - "&3Mined: %s%b &3Broke: &7%b", + + String message = String.format( "- &3TargetBlock: &7%s " + + "&3Mined: %s%b &3Broke: &7%b &3Counted: &7%b", targetBlock.getPrisonBlock().getBlockName(), (targetBlock.isMined() ? "&d" : "&2"), targetBlock.isMined(), - targetBlock.isAirBroke() + targetBlock.isAirBroke(), + targetBlock.isCounted() ); - player.sendMessage( message ); - Output.get().logInfo( message ); + output.add( message ); +// player.sendMessage( message ); +// Output.get().logInfo( message ); - String message2 = String.format( " &3Counted: &7%b &3Edge: &7%b " + - "&3Exploded: %s%b &3IgnoreAllEvents: &7%b", - targetBlock.isCounted(), + String message2 = String.format( "- &3isEdge: &7%b " + + "&3Exploded: %s%b &3IgnoreAllEvents: &7%b", + targetBlock.isEdge(), (targetBlock.isExploded() ? "&d" : "&2"), targetBlock.isExploded(), targetBlock.isIgnoreAllBlockEvents() ); - player.sendMessage( message2 ); - Output.get().logInfo( message2 ); + output.add( message2 ); +// player.sendMessage( message2 ); +// Output.get().logInfo( message2 ); } } if ( !isSneaking ) { - player.sendMessage( + output.add( String.format( " &d(&7Sneak to test BlockBreakEvent with block.&d)" ) ); @@ -188,11 +225,22 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { // Debug the block break events: - dumpBlockBreakEvent( player, sBlock, targetBlock ); + dumpBlockBreakEvent( player, sBlock, targetBlock, output ); } + + output.add( " - - End DebugBlockInfo - - " ); + for ( String outputLine : output ) { + boolean playerMessage = outputLine.startsWith( "-" ); + if ( playerMessage ) { + outputLine = outputLine.substring( 1 ); + + player.sendMessage( outputLine ); + } + Output.get().logInfo( outputLine ); + } @@ -215,10 +263,15 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { // // checkForEvent(e.getPlayer(), sel); // } + + // disable active prior to exiting function: + //this.active = false; + } - public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTargetPrisonBlock targetBlock ) { - List output = new ArrayList<>(); + public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTargetPrisonBlock targetBlock, + List output ) { +// List output = new ArrayList<>(); SpigotBlock checkBlock = sBlock; @@ -292,18 +345,33 @@ public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTa ) ); - printEventStatus( bbe, "-initial-", "", checkBlock, targetBlock, tool, output, player ); + EventDropsStatus isNs = isDropCanceled( bbe ); + + + output.add( " &3Legend: &7EP&3: EventPriority &7EC&3: EventCanceled " + + "&7DC&3: DropsCanceled &7EB&3: EventBlock &7Ds&3: Drops " + + "&7ms&3: dur ms" + + ( isNs == EventDropsStatus.notSupported ? " &7NS&3: NotSupported" : "" ) + ); + + + printEventStatus( bbe, "-initial-", "", checkBlock, targetBlock, tool, output, player, -1 ); for ( RegisteredListener listener : bbe.getHandlers().getRegisteredListeners() ) { + long start = 0; + long stop = 0; + try { // boolean isPrison = listener.getPlugin().getName().equalsIgnoreCase( "Prison" ); // boolean isSpigotListener = isPrison && listener.getListener() instanceof SpigotListener; // if ( !isSpigotListener ) { + start = System.nanoTime(); listener.callEvent( bbe ); + stop = System.nanoTime(); // } } @@ -316,9 +384,15 @@ public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTa } + double durationNano = (stop - start); + + if ( durationNano > 0 ) { + durationNano = durationNano / 1_000_000; + } + printEventStatus( bbe, listener.getPlugin().getName(), listener.getPriority().name(), checkBlock, targetBlock, - tool, output, player ); + tool, output, player, durationNano ); } @@ -326,10 +400,10 @@ public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTa // Put the heldItem back in the player's hand, which should be the prison wand: SpigotCompatibility.getInstance().setItemInMainHand( player.getWrapper(), heldItem ); - for ( String outputLine : output ) - { - Output.get().logInfo( outputLine ); - } +// for ( String outputLine : output ) +// { +// Output.get().logInfo( outputLine ); +// } } @@ -363,9 +437,11 @@ private void printEventStatus( BlockBreakEvent bbe, MineTargetPrisonBlock targetBlock, SpigotItemStack tool, List output, - SpigotPlayer player ) { + SpigotPlayer player, + double durationNano ) { StringBuilder sb = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); sb.append( " " ); boolean isCanceled = bbe.isCancelled(); @@ -375,7 +451,7 @@ private void printEventStatus( BlockBreakEvent bbe, dropStats = "&4" + isDropCanceled.name(); } else if ( isDropCanceled == EventDropsStatus.notSupported ) { - dropStats = "&d" + isDropCanceled.name(); + dropStats = "&dNS"; // + isDropCanceled.name(); } // Get a fresh copy of the block to ensure we pickup the latest status: @@ -386,30 +462,13 @@ else if ( isDropCanceled == EventDropsStatus.notSupported ) { bukkitDrops = obbMines.mergeDrops( bukkitDrops ); - String msg = String.format( " &3Plugin: &7%-15s &2EventPriority: &7%-9s " - + "&2EventCanceled: &7%5s &2DropsCanceled: &7%s", - plugin, - ( priority == null ? "$dnone" : priority ), - ( isCanceled ? "&4true " : "false" ), - dropStats - ); - sb.append( msg ); - - - - - output.add( sb.toString() ); - sb.setLength( 0 ); - SpigotBlock eventBlock = SpigotBlock.getSpigotBlock( bbe.getBlock() ); - - String msg2 = String.format( " &aEventBlock: &b%s ", - eventBlock == null ? - "&4none" : - eventBlock.getBlockNameFormal() ); - sb.append( msg2 ); + String eventBlockName = eventBlock == null ? + "&4none" : + eventBlock.getBlockNameFormal(); + - sb.append( " &aDrops:" ); + // Build the drops listing: if ( bukkitDrops.size() > 0 ) { // List drops = sBlk.getDrops( tool ); @@ -417,20 +476,68 @@ else if ( isDropCanceled == EventDropsStatus.notSupported ) { { // SpigotItemStack sis = (SpigotItemStack) itemStack; - sb.append( " &b" ).append( itemStack.getName() ); + sb2.append( " &b" ).append( itemStack.getName() ); if ( itemStack.getAmount() > 0 ) { - sb.append( "&a(&b" ).append( itemStack.getAmount() ).append( "&a)" ); + sb2.append( "&a(&b" ).append( itemStack.getAmount() ).append( "&a)" ); } } } else { - sb.append( "&4none" ); + sb2.append( "&4none" ); } - if ( sb.length() > 0 ) { - output.add( sb.toString() ); - sb.setLength( 0 ); - } + + DecimalFormat dFmt = new DecimalFormat("#,##0.000000"); + String durationNanoStr = durationNano == -1 ? "---" : dFmt.format( durationNano ); + + + String msg = String.format( " &3Plugin: &7%-15s &2EP: &7%-9s " + + "&2EC: &7%5s &2DC: &7%s &aEB: &b%s &aDs: %s &ams: &7%s", + plugin, + ( priority == null ? "$dnone" : priority ), + ( isCanceled ? "&4true " : "false" ), + dropStats, + eventBlockName, + sb2, + durationNanoStr + ); + sb.append( msg ); + + + output.add( sb.toString() ); + + +// sb.setLength( 0 ); + + +// String msg2 = String.format( " &aEventBlock: &b%s ", +// eventBlock == null ? +// "&4none" : +// eventBlock.getBlockNameFormal() ); +// sb.append( msg2 ); + +// sb.append( " &aDrops:" ); +// if ( bukkitDrops.size() > 0 ) { +// +//// List drops = sBlk.getDrops( tool ); +// for ( ItemStack itemStack : bukkitDrops ) +// { +//// SpigotItemStack sis = (SpigotItemStack) itemStack; +// +// sb.append( " &b" ).append( itemStack.getName() ); +// if ( itemStack.getAmount() > 0 ) { +// sb.append( "&a(&b" ).append( itemStack.getAmount() ).append( "&a)" ); +// } +// } +// } +// else { +// sb.append( "&4none" ); +// } + +// if ( sb.length() > 0 ) { +// output.add( sb.toString() ); +// sb.setLength( 0 ); +// } } @@ -438,7 +545,7 @@ private EventDropsStatus isDropCanceled( BlockBreakEvent bbe ) { EventDropsStatus results = EventDropsStatus.normal; try { - if ( bbe.isDropItems() ) { + if ( !bbe.isDropItems() ) { results = EventDropsStatus.canceled; } else { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java index 880241c65..74c95c85d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java @@ -11,6 +11,8 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; + +import tech.mcprison.prison.Prison; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.compat.Compatibility; @@ -130,9 +132,11 @@ private void backpackItemClickAction(PlayerInteractEvent e) { if (materialConf != null && inHandItem != null && inHandItem.getType() == materialConf.getType() && inHandItem.hasItemMeta() && inHandItem.getItemMeta().hasDisplayName() && inHandItem.getItemMeta().getDisplayName().equalsIgnoreCase(SpigotPrison.format(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Item_Title")))) { if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ - Bukkit.dispatchCommand(p, "gui backpackslist"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "gui backpackslist" )); } else { - Bukkit.dispatchCommand(p, "gui backpack"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "gui backpack" )); } e.setCancelled(true); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 760da3281..3017e4ec4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -1,6 +1,5 @@ package tech.mcprison.prison.spigot.block; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -36,7 +35,6 @@ import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.utils.BlockUtils; -import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; import tech.mcprison.prison.util.Text; public abstract class OnBlockBreakEventCore @@ -276,7 +274,7 @@ protected void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) int count = 0; for ( SpigotBlock spigotBlock : blocks ) { - if ( count++ % 10 == 0 && pmEvent.getMine() != null && + if ( count++ % 20 == 0 && pmEvent.getMine() != null && !pmEvent.getMine().getMineStateMutex().isMinable() ) { SpigotPlayer sPlayer = pmEvent.getSpigotPlayer(); @@ -328,6 +326,30 @@ private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreak return blocks; } + + /** + *

Used with BlockConverters event triggers. + *

+ * + * @param pmEvent + * @param minedBlock + * @param targetBlock + * @return + */ + protected SpigotBlock finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent, + SpigotBlock minedBlock, MineTargetPrisonBlock targetBlock ) { + SpigotBlock results = null; + + if ( targetBlock.getPrisonBlock().getBlockName().equalsIgnoreCase( minedBlock.getBlockName() ) ) { + results = minedBlock; + targetBlock.setAirBroke( true ); + + // Count the blocks that were mined: + countBlocksMined( pmEvent, pmEvent.getTargetBlock() ); + } + + return results; + } /** @@ -350,6 +372,8 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) StringBuilder debugInfo = pmEvent.getDebugInfo(); + debugInfo.append( "{br}|| validateEvent:: " ); + SpigotBlock sBlockHit = pmEvent.getSpigotBlock(); // Mine should already be set: @@ -398,7 +422,9 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) // NOTE: I have no idea why 25 blocks and less should be bypassed for validation: boolean bypassMatchedBlocks = pmEvent.getMine().getBounds().getTotalBlockCount() <= 25; if ( bypassMatchedBlocks ) { + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(TargetBlock match requirement is disabled [blocks<=25]) " ); + pmEvent.setDebugColorCodeDebug(); } boolean matchedBlocks = isBlockAMatch( targetBlock, sBlockHit ); @@ -407,6 +433,7 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) // and the block has not been mined before, then allow the breakage by // setting bypassMatchedBlocks to true to allow normal processing: if ( !matchedBlocks && + targetBlock != null && !targetBlock.isMined() && sBlockHit.isAir() && pmEvent.getBbPriority().isMonitor() ) { @@ -421,6 +448,8 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) targetBlock.isExploded()) ) { // debugInfo.setLength( 0 ); + + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(Primary TargetBlock forcedFastFail validateEvent [ "); if ( targetBlock.isIgnoreAllBlockEvents() ) { debugInfo.append( "ignoreAllBlockEvents " ); @@ -429,6 +458,7 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) debugInfo.append( "alreadyExploded" ); } debugInfo.append( "]) " ); + pmEvent.setDebugColorCodeDebug(); pmEvent.setForceIfAirBlock( false ); @@ -529,7 +559,9 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) // This block has already been mined and is not a mine bomb, so fail the validation // and cancel the event since if it's not an air block, it may be another effect that // is placing a block within the mine, such as a prison util's decay function. + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "VALIDATION_FAILED_BLOCK_ALREADY_MINED " ); + pmEvent.setDebugColorCodeDebug(); results = false; @@ -541,7 +573,9 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) else { noTargetBlock++; + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "VALIDATION_FAILED_NO_TARGETBLOCK " ); + pmEvent.setDebugColorCodeDebug(); results = false; } @@ -675,8 +709,10 @@ else if ( targetExplodedBlock.isMined() ) { } if ( unbreakable > 0 ) { + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + " blocks, event not canceled) " ); + pmEvent.setDebugColorCodeDebug(); } if ( outsideOfMine > 0 ) { @@ -700,8 +736,10 @@ else if ( targetExplodedBlock.isMined() ) { } if ( blockTypeNotExpected > 0 ) { + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "BLOCK_TYPE_NOT_EXPECTED__CANNOT_PROCESS (" + blockTypeNotExpected + " ) " ); + pmEvent.setDebugColorCodeDebug(); } @@ -729,7 +767,9 @@ else if ( targetExplodedBlock.isMined() ) { // Ignore event and clear debugInfo: // debugInfo.setLength( 0 ); + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(TargetBlock forcedFastFail validateEvent [BlockAlreadyMined]) " ); + pmEvent.setDebugColorCodeDebug(); return results; } @@ -737,7 +777,7 @@ else if ( targetExplodedBlock.isMined() ) { } - debugInfo.append( "blocks(" ) + debugInfo.append( " blocks(" ) .append( pmEvent.getBlock() == null ? "0" : "1" ) .append( "+" ) .append( pmEvent.getExplodedBlocks().size() ) @@ -753,14 +793,18 @@ else if ( targetExplodedBlock.isMined() ) { // "&cYour tool is worn-out and cannot be used." ); pmEvent.setCancelOriginalEvent( true ); + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); + pmEvent.setDebugColorCodeDebug(); results = false; } if ( mine != null && BlockUtils.getInstance().isUnbreakable( sBlockHit ) ) { // The block is unbreakable because a utility has it locked: pmEvent.setCancelOriginalEvent( true ); + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (event canceled) " ); + pmEvent.setDebugColorCodeDebug(); results = false; } if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && @@ -772,9 +816,11 @@ else if ( targetExplodedBlock.isMined() ) { mine.isAccessPermissionEnabled() ? "Perms" : "Other?"; pmEvent.setCancelOriginalEvent( true ); + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "ACCESS_DENIED (event canceled - Access by " ) .append( accessType ) .append( ") " ); + pmEvent.setDebugColorCodeDebug(); results = false; } @@ -849,7 +895,9 @@ else if ( targetExplodedBlock.isMined() ) { else if ( results && pmEvent.getBbPriority().isMonitor() && mine == null ) { // bypass all processing since the block break is outside any mine: + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(MONITOR bypassed: no mine) " ); + pmEvent.setDebugColorCodeDebug(); results = false; } @@ -867,32 +915,39 @@ else if ( results && pmEvent.getBbPriority().isMonitor() && mine != null ) { debugInfo.append( "(BLOCKEVENTS processing) " ); - // This is true if the player cannot toggle the autosell, and it's - // true if they can, and the have it enabled: - boolean isPlayerAutosellEnabled = SellAllUtil.get() != null && - SellAllUtil.get().checkIfPlayerAutosellIsActive( - pmEvent.getSpigotPlayer().getWrapper() ) - ; - - // AutoSell on full inventory when using BLOCKEVENTS: - if ( isBoolean( AutoFeatures.isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority ) && - SpigotPrison.getInstance().isSellAllEnabled() && - isPlayerAutosellEnabled && - pmEvent.getSpigotPlayer().isInventoryFull() ) { + if ( SpigotPrison.getInstance().isSellAllEnabled() ) { + SellAllUtil sellAllUtil = SellAllUtil.get(); - final long nanoStart = System.nanoTime(); - boolean success = SellAllUtil.get().sellAllSell( pmEvent.getPlayer(), - false, false, false, true, true, false); - final long nanoStop = System.nanoTime(); - double milliTime = (nanoStop - nanoStart) / 1000000d; + // This will return true (allow autosell) unless players can toggle autosell and they turned it off: + // This is to be used with other auto sell setting, but never on it's own: + boolean isPlayerAutosellEnabled = + (!sellAllUtil.isAutoSellPerUserToggleable || + sellAllUtil.isSellallPlayerUserToggleEnabled( + pmEvent.getPlayer() )); - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - debugInfo.append( "(autosell BLOCKEVENTS: " + (success ? "success" : "failed") + - " ms: " + dFmt.format( milliTime ) + ") "); - PlayerAutoRankupTask.autoSubmitPlayerRankupTask( pmEvent.getSpigotPlayer(), debugInfo ); + // AutoSell on full inventory when using BLOCKEVENTS: + if ( isBoolean( AutoFeatures.isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority ) && + isPlayerAutosellEnabled && + pmEvent.getSpigotPlayer().isInventoryFull() ) { + + pmEvent.performSellAllOnPlayerInventoryLogged("BLOCKEVENTS priority sellall"); + +// final long nanoStart = System.nanoTime(); +// boolean success = SellAllUtil.get().sellAllSell( pmEvent.getPlayer(), +// false, false, false, true, true, false); +// final long nanoStop = System.nanoTime(); +// double milliTime = (nanoStop - nanoStart) / 1000000d; +// +// DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); +// debugInfo.append( "(autosell BLOCKEVENTS: " + (success ? "success" : "failed") + +// " ms: " + dFmt.format( milliTime ) + ") "); +// +// PlayerAutoRankupTask.autoSubmitPlayerRankupTask( pmEvent.getSpigotPlayer(), debugInfo ); +// + } } } @@ -969,10 +1024,14 @@ else if ( results && pmEvent.getBbPriority().isMonitor() && mine != null ) { debugInfo.append( "(PassedValidation) " ); } else { + pmEvent.setDebugColorCodeWarning(); debugInfo.append( "(ValidationFailed) " ); + pmEvent.setDebugColorCodeDebug(); } +// debugInfo.append( "{br}|| " ); + return results; } @@ -1233,7 +1292,9 @@ public boolean applyDropsBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, int success = true; } else { + pmEvent.setDebugColorCodeWarning(); pmEvent.getDebugInfo().append( "(fail:totalDrops=0) "); + pmEvent.setDebugColorCodeDebug(); } return success; @@ -1707,7 +1768,8 @@ protected int getDurabilityResistance(SpigotItemStack itemInHand, String itemLor try { results += Integer.parseInt(val); } catch (NumberFormatException e1) { - Output.get().logError("AutoManager: tool durability failure. lore= [" + s + "] val= [" + val + "] error: " + e1.getMessage()); + Output.get().logError("AutoManager: tool durability failure. " + + "lore= [" + s + "] val= [" + val + "] error: " + e1.getMessage()); } break; 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 d7ad293f5..f693a3c41 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 @@ -17,6 +17,9 @@ import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsExplosiveEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsJackHammerEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerTokenEnchant; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonExplosionTriggerEvent; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonLayerTriggerEvent; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerXPrisonNukeTriggerEvent; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerZenchantments; import tech.mcprison.prison.spigot.autofeatures.events.PrisonDebugBlockInspector; @@ -111,10 +114,16 @@ public class OnBlockBreakEventListener private AutoManagerRevEnchantsExplosiveEvent reEEvents; private AutoManagerRevEnchantsJackHammerEvent reJHEvents; - + private AutoManagerXPrisonExplosionTriggerEvent xpExpEvents; + private AutoManagerXPrisonLayerTriggerEvent xpLayerEvents; + private AutoManagerXPrisonNukeTriggerEvent xpNukeEvents; + + private PrisonDebugBlockInspector pdBlockInspector; + + public OnBlockBreakEventListener() { super(); @@ -208,32 +217,66 @@ public void reloadEventListeners() { private void registerEvents() { bbEvents = new AutoManagerBlockBreakEvents(); - bbEvents.registerEvents(); - + // Prison's own internal event and listener: pebbEvents = new AutoManagerPrisonsExplosiveBlockBreakEvents(); - pebbEvents.registerEvents(); - + + ceEvents = new AutoManagerCrazyEnchants(); + ceEvents = new AutoManagerCrazyEnchants(); - ceEvents.registerEvents(); peEvents = new AutoManagerPrisonEnchants(); - peEvents.registerEvents(); - + teEvents = new AutoManagerTokenEnchant(); - teEvents.registerEvents(); zcEvents = new AutoManagerZenchantments(); - zcEvents.registerEvents(); reEEvents = new AutoManagerRevEnchantsExplosiveEvent(); - reEEvents.registerEvents(); reJHEvents = new AutoManagerRevEnchantsJackHammerEvent(); - reJHEvents.registerEvents(); - pdBlockInspector = new PrisonDebugBlockInspector(); - pdBlockInspector.init(); + + + xpExpEvents = new AutoManagerXPrisonExplosionTriggerEvent(); + + xpLayerEvents = new AutoManagerXPrisonLayerTriggerEvent(); + + xpNukeEvents = new AutoManagerXPrisonNukeTriggerEvent(); + + + + if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + bbEvents.registerEvents(); + + // Prison's own internal event and listener: + pebbEvents.registerEvents(); + + ceEvents.registerEvents(); + + peEvents.registerEvents(); + + teEvents.registerEvents(); + + zcEvents.registerEvents(); + + reEEvents.registerEvents(); + + reJHEvents.registerEvents(); + + + xpExpEvents.registerEvents(); + + xpLayerEvents.registerEvents(); + + xpNukeEvents.registerEvents(); + + } + + pdBlockInspector = PrisonDebugBlockInspector.getInstance(); + pdBlockInspector.getClass(); + +// pdBlockInspector.init(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index 382a535fb..a99068edd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -92,9 +92,9 @@ public void logDebugInfo() { "" : getSpigotBlock().getLocation().toWorldCoordinates(); - Output.get().logInfo( "Prison AutoFeatures Fast-Fail: %s %s %s %s %s%s", + Output.get().logInfo( "Prison AutoFeatures Fast-Fail: %s %s %s %s%s", getResultsReason().name(), - getBbPriority().name(), + //getBbPriority().name(), getSpigotPlayer().getName(), getMine() == null ? "noMine" : getMine().getName(), @@ -115,9 +115,9 @@ public String getDebugInfo() { getSpigotBlock().getLocation().toWorldCoordinates(); return String.format( - "AutoFeatures: %s %s %s %s %s%s ", + "{br}|| EventInfo: %s %s Mine: %s %s %s ", getResultsReason().name(), - getBbPriority().name(), +// getBbPriority().name(), getSpigotPlayer().getName(), getMine() == null ? "noMine" : getMine().getName(), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java index 4ea130819..5d5e0f551 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java @@ -267,12 +267,13 @@ protected void autoFeatureBlock( Player p, XMaterial source, StringBuilder debug - protected void autoSmelt( boolean autoSmelt, XMaterial source, XMaterial target, Player p, StringBuilder debugInfo ) { + protected void autoSmelt( boolean autoSmelt, XMaterial source, XMaterial target, + Player p, StringBuilder debugInfo ) { if ( autoSmelt && source != null && target != null ) { HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, 1 ); - dropExtra( overflow, p, debugInfo ); + dropExtra( overflow, p, debugInfo, false ); } } @@ -283,11 +284,12 @@ protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, } - protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, int ratio, Player p, StringBuilder debugInfo ) { + protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, int ratio, + Player p, StringBuilder debugInfo ) { if ( autoBlock && source != null && target != null ) { HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, ratio ); - dropExtra( overflow, p, debugInfo ); + dropExtra( overflow, p, debugInfo, false ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java index 4d07b0d54..5c8648c2c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java @@ -29,8 +29,9 @@ private void backpackMainCommand(CommandSender sender, description = "Leave empty if you want to open your main backpack, add an ID if you've more than one.") String id){ if (sender.hasPermission("prison.admin") || sender.isOp()){ - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("backpack help"); - sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("backpack help"); +// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("backpack help"); +// sender.dispatchCommand(registeredCmd); return; } @@ -277,79 +278,79 @@ private void openBackpackAdminGUI(CommandSender sender){ BackpacksAdminGUI gui = new BackpacksAdminGUI(p); gui.open(); } - - @Command(identifier = "gui backpack", description = "Backpack as a GUI", onlyPlayers = true) - private void backpackGUIOpenCommand(CommandSender sender, - @Arg(name = "Backpack-ID", def = "null", - description = "If user have more than backpack, he'll be able to choose another backpack on ID") String id){ - - Player p = getSpigotPlayer(sender); - - if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if (isDisabledWorld(p)) return; - - if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled")) && (BackpacksUtil.get().reachedBackpacksLimit(p) && !BackpacksUtil.get().getBackpacksIDs(p).contains(id))){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_reached) + " [" + BackpacksUtil.get().getNumberOwnedBackpacks(p) + "]")); - return; - } - - if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); - return; - } - - if (!BackpacksUtil.get().canOwnBackpack(p)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_cant_own))); - return; - } - - // New method. - if (!id.equalsIgnoreCase("null") && getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ - BackpacksUtil.get().openBackpack(p, id); - } else { - BackpacksUtil.get().openBackpack(p, (String) null ); - } - } - - @Command(identifier = "gui backpackslist", description = "Backpack as a GUI", onlyPlayers = true) - private void backpackListGUICommand(CommandSender sender){ - Player p = getSpigotPlayer(sender); - - if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if (isDisabledWorld(p)) return; - - // New method. - if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ - if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); - return; - } - BackpacksListPlayerGUI gui = new BackpacksListPlayerGUI(p); - gui.open(); - } - } - - @Command(identifier = "gui backpackadmin", description = "Open backpack admin GUI", permissions = "prison.admin", onlyPlayers = true) - private void openBackpackAdminCommandGUI(CommandSender sender){ - - Player p = getSpigotPlayer(sender); - - if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - BackpacksAdminGUI gui = new BackpacksAdminGUI(p); - gui.open(); - } +// +// @Command(identifier = "gui backpack", description = "Backpack as a GUI", onlyPlayers = true) +// private void backpackGUIOpenCommand(CommandSender sender, +// @Arg(name = "Backpack-ID", def = "null", +// description = "If user have more than backpack, he'll be able to choose another backpack on ID") String id){ +// +// Player p = getSpigotPlayer(sender); +// +// if (p == null) { +// Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); +// return; +// } +// +// if (isDisabledWorld(p)) return; +// +// if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled")) && (BackpacksUtil.get().reachedBackpacksLimit(p) && !BackpacksUtil.get().getBackpacksIDs(p).contains(id))){ +// Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_reached) + " [" + BackpacksUtil.get().getNumberOwnedBackpacks(p) + "]")); +// return; +// } +// +// if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ +// Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); +// return; +// } +// +// if (!BackpacksUtil.get().canOwnBackpack(p)){ +// Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_cant_own))); +// return; +// } +// +// // New method. +// if (!id.equalsIgnoreCase("null") && getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ +// BackpacksUtil.get().openBackpack(p, id); +// } else { +// BackpacksUtil.get().openBackpack(p, (String) null ); +// } +// } +// +// @Command(identifier = "gui backpackslist", description = "Backpack as a GUI", onlyPlayers = true) +// private void backpackListGUICommand(CommandSender sender){ +// Player p = getSpigotPlayer(sender); +// +// if (p == null) { +// Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); +// return; +// } +// +// if (isDisabledWorld(p)) return; +// +// // New method. +// if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ +// if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ +// Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); +// return; +// } +// BackpacksListPlayerGUI gui = new BackpacksListPlayerGUI(p); +// gui.open(); +// } +// } +// +// @Command(identifier = "gui backpackadmin", description = "Open backpack admin GUI", permissions = "prison.admin", onlyPlayers = true) +// private void openBackpackAdminCommandGUI(CommandSender sender){ +// +// Player p = getSpigotPlayer(sender); +// +// if (p == null) { +// Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); +// return; +// } +// +// BackpacksAdminGUI gui = new BackpacksAdminGUI(p); +// gui.open(); +// } private boolean isDisabledWorld(Player p) { String worldName = p.getWorld().getName(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUIBackPackCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUIBackPackCommands.java new file mode 100644 index 000000000..b301ba73e --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUIBackPackCommands.java @@ -0,0 +1,103 @@ +package tech.mcprison.prison.spigot.commands; + +import java.util.List; + +import org.bukkit.entity.Player; + +import tech.mcprison.prison.commands.Arg; +import tech.mcprison.prison.commands.Command; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.MessagesConfig; +import tech.mcprison.prison.spigot.gui.backpacks.BackpacksAdminGUI; +import tech.mcprison.prison.spigot.gui.backpacks.BackpacksListPlayerGUI; + +public class PrisonSpigotGUIBackPackCommands + extends PrisonSpigotBaseCommands +{ + + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); + + @Command(identifier = "gui backpack", description = "Backpack as a GUI", onlyPlayers = true) + private void backpackGUIOpenCommand(CommandSender sender, + @Arg(name = "Backpack-ID", def = "null", + description = "If user have more than backpack, he'll be able to choose another backpack on ID") String id){ + + Player p = getSpigotPlayer(sender); + + if (p == null) { + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + if (isDisabledWorld(p)) return; + + if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled")) && (BackpacksUtil.get().reachedBackpacksLimit(p) && !BackpacksUtil.get().getBackpacksIDs(p).contains(id))){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_reached) + " [" + BackpacksUtil.get().getNumberOwnedBackpacks(p) + "]")); + return; + } + + if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); + return; + } + + if (!BackpacksUtil.get().canOwnBackpack(p)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_cant_own))); + return; + } + + // New method. + if (!id.equalsIgnoreCase("null") && getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ + BackpacksUtil.get().openBackpack(p, id); + } else { + BackpacksUtil.get().openBackpack(p, (String) null ); + } + } + + @Command(identifier = "gui backpackslist", description = "Backpack as a GUI", onlyPlayers = true) + private void backpackListGUICommand(CommandSender sender){ + Player p = getSpigotPlayer(sender); + + if (p == null) { + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + if (isDisabledWorld(p)) return; + + // New method. + if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ + if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); + return; + } + BackpacksListPlayerGUI gui = new BackpacksListPlayerGUI(p); + gui.open(); + } + } + + @Command(identifier = "gui backpackadmin", description = "Open backpack admin GUI", permissions = "prison.admin", onlyPlayers = true) + private void openBackpackAdminCommandGUI(CommandSender sender){ + + Player p = getSpigotPlayer(sender); + + if (p == null) { + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + BackpacksAdminGUI gui = new BackpacksAdminGUI(p); + gui.open(); + } + + + private boolean isDisabledWorld(Player p) { + String worldName = p.getWorld().getName(); + List disabledWorlds = BackpacksUtil.get().getBackpacksConfig().getStringList("Options.DisabledWorlds"); + return disabledWorlds.contains(worldName); + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUISellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUISellAllCommands.java new file mode 100644 index 000000000..e9bfee34c --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUISellAllCommands.java @@ -0,0 +1,78 @@ +package tech.mcprison.prison.spigot.commands; + +import org.bukkit.entity.Player; + +import tech.mcprison.prison.commands.Arg; +import tech.mcprison.prison.commands.Command; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.sellall.messages.SpigotVariousGuiMessages; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.MessagesConfig; +import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminBlocksGUI; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; + +public class PrisonSpigotGUISellAllCommands + extends PrisonSpigotBaseCommands { + + + @Command(identifier = "sellall gui", + description = "SellAll GUI command", +// aliases = "gui sellall", + permissions = "prison.admin", onlyPlayers = true) + private void sellAllGuiCommand(CommandSender sender, + @Arg(name = "page", description = "If there are more than 45 items, then they " + + "will be shown on multiple pages. The page parameter starts with " + + "page 1.", def = "1" ) int page){ + + if (!PrisonSpigotSellAllCommands.isEnabled()) return; + + Player p = getSpigotPlayer(sender); + + // Sender must be a Player, not something else like the Console. + if (p == null) { + Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); + return; + } + + if ( !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (!sellAllUtil.openSellAllGUI( p, page, "sellall gui", "close" )){ + // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. + if (p.hasPermission("prison.admin")) { + + new SpigotVariousGuiMessages().sellallGUIIsDisabledMsg(sender); +// Output.get().sendError(sender, +// messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_disabled)); + } + } + } + + @Command(identifier = "sellall gui blocks", + description = "SellAll GUI Blocks command", + aliases = "gui sellall", + permissions = "prison.admin", onlyPlayers = true) + private void sellAllGuiBlocksCommand(CommandSender sender, + @Arg(name = "page", description = "If there are more than 45 items, then they " + + "will be shown on multiple pages. The page parameter starts with " + + "page 1.", def = "1" ) int page){ + + if (!PrisonSpigotSellAllCommands.isEnabled()) return; + + Player p = getSpigotPlayer(sender); + + // Sender must be a Player, not something else like the Console. + if (p == null) { + Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); + return; + } + + SellAllAdminBlocksGUI saBlockGui = new SellAllAdminBlocksGUI( p, page, "sellall gui blocks", "sellall gui" ); + saBlockGui.open(); + + } + +} 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 da434a465..688191607 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 @@ -116,7 +116,8 @@ public void prisonManagerPrestige(CommandSender sender, // } // // if ( PrisonRanks.getInstance().getLadderManager().getLadder("prestiges") == null ) { -// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ranks ladder create prestiges"); +// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), +// Prison.get().getCommandHandler().findRegisteredCommand( "ranks ladder create prestiges" )); // } // // PrisonRanks rankPlugin; @@ -166,7 +167,8 @@ public void prisonManagerPrestige(CommandSender sender, // } // else { // // Bypassing prestige confirmations: -// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "rankup prestiges"); +// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), +// Prison.get().getCommandHandler().findRegisteredCommand( "rankup prestiges" )); // } // } // } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index 9bb582477..cb5c734cc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -2,6 +2,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.TreeMap; @@ -17,16 +18,18 @@ import tech.mcprison.prison.commands.Wildcard; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.sellall.messages.SpigotVariousGuiMessages; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.data.Rank; +import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.spigot.SpigotPlatform; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.configs.MessagesConfig; -import tech.mcprison.prison.spigot.game.SpigotOfflinePlayer; import tech.mcprison.prison.spigot.game.SpigotPlayer; -import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminBlocksGUI; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; @@ -73,17 +76,18 @@ private void sellAllCurrency(CommandSender sender, return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (sellAllUtil.setCurrency(currency)){ Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_edit_success) + " [" + currency + "]"); } } - @Command(identifier = "sellall", description = "SellAll main command", + @Command(identifier = "sellall", + description = "SellAll main command", altPermissions = {"-none-", "prison.admin"}, onlyPlayers = false) private void sellAllCommands(CommandSender sender) { @@ -91,31 +95,37 @@ private void sellAllCommands(CommandSender sender) { if (!isEnabled()) return; if (sender.hasPermission("prison.admin")) { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall help" ); - sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall help"); +// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall help" ); +// sender.dispatchCommand(registeredCmd); } else { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); - sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall sell"); +// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); +// sender.dispatchCommand(registeredCmd); } } - @Command(identifier = "sellall delay", description = "SellAll delay.", + @Command(identifier = "sellall set delay", + description = "Enables or disables a SellAll cooldown delay to prevent " + + "players from spamming the sellall command. " + + "See `/sellall set delayTime`.", onlyPlayers = false, permissions = "prison.sellall.delay") private void sellAllDelay(CommandSender sender, - @Arg(name = "boolean", description = "True to enable or false to disable.", def = "null") String enable){ + @Arg(name = "boolean", + description = "True to enable or false to disable.", + def = "false") String enable){ - if (!isEnabled()) return; + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } boolean enableBoolean = getBoolean(enable); if (sellAllUtil.isSellAllDelayEnabled == enableBoolean){ @@ -136,17 +146,17 @@ private void sellAllDelay(CommandSender sender, } } - @Command(identifier = "sellall set delay", description = "Edit SellAll delay.", + @Command(identifier = "sellall set delayTime", + description = "This sets the sellall cooldown delay to the specified number of seconds.", onlyPlayers = false, permissions = "prison.sellall.delay") private void sellAllDelaySet(CommandSender sender, - @Arg(name = "delay", description = "Set delay value in seconds.", def = "0") String delay){ + @Arg(name = "delay", + description = "Set delay value in seconds. Defaults to a value of 15 seconds.", def = "15") String delay){ - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); int delayValue; try { @@ -161,28 +171,32 @@ private void sellAllDelaySet(CommandSender sender, } } - @Command(identifier = "sellall autosell", description = "Enable SellAll AutoSell.", + @Command(identifier = "sellall set autosell", + description = "Enable SellAll AutoSell. " + + "For AutoFeatures based sellall, please see the AutoFeatures configs.", onlyPlayers = false, permissions = "prison.autosell.edit") private void sellAllAutoSell(CommandSender sender, - @Arg(name = "boolean", description = "True to enable or false to disable.", def = "null") String enable){ + @Arg(name = "boolean", + description = "'True' to enable or 'false' to disable. Use 'perUserToggleable' to " + + "enable with users being able to turn on/off. Default value is 'true'. " + + "[true false perUserToggleable]", + def = "true") String enable){ - if (!isEnabled()) return; + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (enable.equalsIgnoreCase("perusertoggleable")){ sellAllAutoSellPerUserToggleable(sender, enable); return; } - if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ + if (!enable.equalsIgnoreCase("true") && !enable.equalsIgnoreCase("false") ){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } - boolean enableBoolean = getBoolean(enable); if (sellAllUtil.isAutoSellEnabled == enableBoolean){ if (enableBoolean){ @@ -202,20 +216,26 @@ private void sellAllAutoSell(CommandSender sender, } } - @Command(identifier = "sellall autosell perUserToggleable", description = "Enable AutoSell perUserToggleable.", + @Command(identifier = "sellall set autosellPerUserToggleable", + description = "Enable AutoSell perUserToggleable. This will " + + "enable autosell if it's not already enabled, plus it will allow players to " + + "turn autosell on/off when they need to using the " + + "command `/sellall autoSellToggle` or the alias `/autosell`. " + + "If user toggleable is disabled through this command, it will also disable " + + "autosell, so you may need to turn it back on with `/sellall set autosell true`.", onlyPlayers = false, permissions = "prison.autosell.edit") private void sellAllAutoSellPerUserToggleable(CommandSender sender, - @Arg(name = "boolean", description = "True to enable or false to disable", def = "null") String enable){ - - if (!isEnabled()) return; + @Arg(name = "boolean", + description = "'True' to enable or 'false' to disable. [true false]", + def = "") String enable){ - if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ - Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); - return; + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + + if ( !enable.equalsIgnoreCase("true") && !enable.equalsIgnoreCase("false") ) { + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } @@ -243,8 +263,8 @@ public void sellAllSellCommand(CommandSender sender, @Arg(name = "player", def = "", description = "An online player name to sell their inventory - " + "Only console or prison commands can include this parameter") String playerName, @Arg(name = "notification", def="", - description = "Notification about the sellall transaction. Defaults to normal. " + - "'silent' suppresses results. [silent]") String notification ){ + description = "Notification behavior for the sellall transaction. Defaults to normal. " + + "'silent' suppresses all notifications. [silent]") String notification ){ if (!isEnabled()) return; @@ -290,12 +310,12 @@ else if (p == null){ } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil.isPlayerInDisabledWorld(p)) return; +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; @@ -313,17 +333,15 @@ else if (p == null){ PlayerAutoRankupTask.autoSubmitPlayerRankupTask( sPlayer, null ); } - @Command(identifier = "sellall hand", description = "Sell only what is in your hand if sellable.", + @Command(identifier = "sellall sellHand", + description = "Sell only what is in your hand if it is sellable.", onlyPlayers = true) public void sellAllSellHandCommand(CommandSender sender){ - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - - if (sellAllUtil == null){ + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllHandEnabled){ Output.get().sendWarn(sender, "The command /sellall hand is disabled from the config!"); @@ -337,7 +355,7 @@ public void sellAllSellHandCommand(CommandSender sender){ return; } - if (sellAllUtil.isPlayerInDisabledWorld(p)) return; +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; @@ -359,19 +377,18 @@ public void sellAllSellHandCommand(CommandSender sender){ } public void sellAllSell(Player p){ - if (!isEnabled()) return; + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (p == null){ Output.get().sendInfo(new SpigotPlayer(p), "&cSorry but you can't use that from the console!"); return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } - if (sellAllUtil.isPlayerInDisabledWorld(p)) return; +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; @@ -389,7 +406,125 @@ public void sellAllSell(Player p){ } - @Command(identifier = "sellall delaysell", description = "Like SellAll Sell command but this will be delayed for some " + + + + @Command(identifier = "sellall valueOf", + description = "SellAll valueOf command will report the total value of the player's inventory " + + "without selling anything.", onlyPlayers = false) + public void sellAllValueOfCommand(CommandSender sender, + @Arg(name = "player", def = "", description = "An online player name to get the value of their inventory - " + + "Only console or prison commands can include this parameter") String playerName + ){ + + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + Player p = getSpigotPlayer(sender); + + + boolean isOp = sender.isOp(); + + tech.mcprison.prison.internal.Player sPlayerAlt = getOnlinePlayer( sender, playerName ); +// if ( sPlayerAlt == null ){ +// // If sPlayerAlt is null then the value in playerName is really intended for notification: +// notification = playerName; +// } + + if ( isOp && !sender.isPlayer() && sPlayerAlt != null ) { + // Only if OP and a valid player name was provided, then OP is trying to run this + // for another player + + if ( !sPlayerAlt.isOnline() ) { + sender.sendMessage( "Player is not online." ); + return; + } + + // Set the active player to who OP specified: + p = ((SpigotPlayer) sPlayerAlt).getWrapper(); + } + + + else if (p == null){ + + if ( getPlayer( sender, playerName ) != null ) { + + Output.get().sendInfo(sender, "&cSorry but the specified player must be online " + + "[/sellall valueOf %s]", playerName ); + } + else { + + Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); + } + + + return; + } + + +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; + + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; + if (permission == null || !p.hasPermission(permission)){ + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); + return; + } + } + + SpigotPlayer sPlayer = new SpigotPlayer( p ); + + String report = sellAllUtil.getPlayerInventoryValueReport( sPlayer ); + + + sender.sendMessage(report); + + PlayerAutoRankupTask.autoSubmitPlayerRankupTask( sPlayer, null ); + } + + @Command(identifier = "sellall valueOfHand", + description = "Get the value of what is in your hand if sellable.", + onlyPlayers = true) + public void sellAllValueOfHandCommand(CommandSender sender){ + + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (!sellAllUtil.isSellAllHandEnabled){ + Output.get().sendWarn(sender, "The command `/sellall valueOfHand` is disabled from the config! (SellAllHandEnabled)"); + return; + } + + Player p = getSpigotPlayer(sender); + + if (p == null){ + Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); + return; + } + +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; + + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; + if (permission == null || !p.hasPermission(permission)){ + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); + return; + } + } + + + String report = sellAllUtil.getItemStackValueReport( + new SpigotPlayer(p), new SpigotItemStack( compat.getItemInMainHand(p)) ); + + sender.sendMessage(report); + } + + + @Command(identifier = "sellall delaysell", + description = "Like SellAll Sell command but this will be delayed for some " + "seconds and if sellall sell commands are triggered during this delay, " + "they will sum up to the total value that will be visible in a notification at the end of the delay. " + "Running more of these commands before a delay have been completed won't reset it and will do the same of /sellall sell " + @@ -397,7 +532,10 @@ public void sellAllSell(Player p){ onlyPlayers = true) public void sellAllSellWithDelayCommand(CommandSender sender){ - if (!isEnabled()) return; + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); Player p = getSpigotPlayer(sender); @@ -406,12 +544,8 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } - if (sellAllUtil.isPlayerInDisabledWorld(p)) return; +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; @@ -433,11 +567,19 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ } - @Command(identifier = "sellall auto toggle", description = "Let the user enable or disable sellall auto", + @Command(identifier = "sellall autoSellToggle", + aliases = {"autosell"}, + description = "When `perUserToggleable` is enabled with autosell, this " + + "command allow the players to enable or disable their own use of autosell. " + + "When using this command, autosell will be toggled on/off for the player. " + + "Can also use the alias `/autosell` to toggle this setting", altPermissions = "prison.sellall.toggle", onlyPlayers = true) private void sellAllAutoEnableUser(CommandSender sender){ - if (!isEnabled()) return; + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); Player p = getSpigotPlayer(sender); @@ -447,12 +589,8 @@ private void sellAllAutoEnableUser(CommandSender sender){ return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } - if (sellAllUtil.isPlayerInDisabledWorld(p)) return; +// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (!sellAllUtil.isAutoSellPerUserToggleable){ return; @@ -464,81 +602,90 @@ private void sellAllAutoEnableUser(CommandSender sender){ return; } - if (sellAllUtil.setAutoSellPlayer(p, !sellAllUtil.isPlayerAutoSellEnabled(p))){ - if (sellAllUtil.isPlayerAutoSellEnabled(p)){ - Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled)); - } else { + boolean isplayerAutosellEnabled = sellAllUtil.isPlayerAutoSellEnabled(p); + if (sellAllUtil.setAutoSellPlayer(p, !isplayerAutosellEnabled)){ + if ( !isplayerAutosellEnabled ){ // Note this variable was negated then saved, so we need to check the negative: Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_disabled)); + } else { + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled)); } } } - - @Command(identifier = "sellall gui", - description = "SellAll GUI command", +// +// @Command(identifier = "sellall gui", +// description = "SellAll GUI command", +//// aliases = "gui sellall", +// permissions = "prison.admin", onlyPlayers = true) +// private void sellAllGuiCommand(CommandSender sender, +// @Arg(name = "page", description = "If there are more than 45 items, then they " + +// "will be shown on multiple pages. The page parameter starts with " + +// "page 1.", def = "1" ) int page){ +// +// if (!isEnabled()) return; +// +// Player p = getSpigotPlayer(sender); +// +// // Sender must be a Player, not something else like the Console. +// if (p == null) { +// Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); +// return; +// } +// +// SellAllUtil sellAllUtil = SellAllUtil.get(); +// if (sellAllUtil == null){ +// return; +// } +// +// if (!sellAllUtil.openSellAllGUI( p, page, "sellall gui", "close" )){ +// // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. +// if (p.hasPermission("prison.admin")) { +// +// new SpigotVariousGuiMessages().sellallGUIIsDisabledMsg(sender); +//// Output.get().sendError(sender, +//// messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_disabled)); +// } +// } +// } +// +// @Command(identifier = "sellall gui blocks", +// description = "SellAll GUI Blocks command", // aliases = "gui sellall", - permissions = "prison.admin", onlyPlayers = true) - private void sellAllGuiCommand(CommandSender sender, - @Arg(name = "page", description = "If there are more than 45 items, then they " + - "will be shown on multiple pages. The page parameter starts with " + - "page 1.", def = "1" ) int page){ - - if (!isEnabled()) return; - - Player p = getSpigotPlayer(sender); - - // Sender must be a Player, not something else like the Console. - if (p == null) { - Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); - return; - } - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } - - if (!sellAllUtil.openSellAllGUI( p, page, "sellall gui", "close" )){ - // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. - if (p.hasPermission("prison.admin")) { - - new SpigotVariousGuiMessages().sellallGUIIsDisabledMsg(sender); -// Output.get().sendError(sender, -// messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_disabled)); - } - } - } - - @Command(identifier = "sellall gui blocks", - description = "SellAll GUI Blocks command", - aliases = "gui sellall", - permissions = "prison.admin", onlyPlayers = true) - private void sellAllGuiBlocksCommand(CommandSender sender, - @Arg(name = "page", description = "If there are more than 45 items, then they " + - "will be shown on multiple pages. The page parameter starts with " + - "page 1.", def = "1" ) int page){ - - if (!isEnabled()) return; - - Player p = getSpigotPlayer(sender); - - // Sender must be a Player, not something else like the Console. - if (p == null) { - Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); - return; - } - - SellAllAdminBlocksGUI saBlockGui = new SellAllAdminBlocksGUI( p, page, "sellall gui blocks", "sellall gui" ); - saBlockGui.open(); - - } - - @Command(identifier = "sellall add", description = "SellAll add an item to the sellAll shop.", +// permissions = "prison.admin", onlyPlayers = true) +// private void sellAllGuiBlocksCommand(CommandSender sender, +// @Arg(name = "page", description = "If there are more than 45 items, then they " + +// "will be shown on multiple pages. The page parameter starts with " + +// "page 1.", def = "1" ) int page){ +// +// if (!isEnabled()) return; +// +// Player p = getSpigotPlayer(sender); +// +// // Sender must be a Player, not something else like the Console. +// if (p == null) { +// Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); +// return; +// } +// +// SellAllAdminBlocksGUI saBlockGui = new SellAllAdminBlocksGUI( p, page, "sellall gui blocks", "sellall gui" ); +// saBlockGui.open(); +// +// } + + @Command(identifier = "sellall items add", + description = "This will add an item to the SellAll shop. " + + "Use `/mines block search help` to find the correct names " + + "for blocks to add to the sellall shop. Use " + + "`/mines block searchAll help` to search for items too.", permissions = "prison.admin", 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){ + @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 (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (itemID == null){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); @@ -551,10 +698,6 @@ private void sellAllAddCommand(CommandSender sender, return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_already_added)); @@ -571,7 +714,7 @@ private void sellAllAddCommand(CommandSender sender, } if (sellAllUtil.addSellAllBlock(blockAdd, value)){ - Output.get().sendInfo(sender, "&3 ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); + Output.get().sendInfo(sender, "&3 ITEM [" + itemID + ", " + value + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } } catch (IllegalArgumentException ex){ @@ -591,10 +734,10 @@ public void sellAllAddCommand(XMaterial blockAdd, Double value){ String itemID = blockAdd.name(); - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); // If the block or item was already configured, then skip this: if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ @@ -606,11 +749,17 @@ public void sellAllAddCommand(XMaterial blockAdd, Double value){ Output.get().logInfo("&3 ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } - @Command(identifier = "sellall delete", description = "SellAll delete command, remove an item from shop.", + @Command(identifier = "sellall items delete", + description = "This command will delete an item from the " + + "sellall shop. Use `/sellall list` to identify which items to revmove.", permissions = "prison.admin", onlyPlayers = false) - private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", description = "The Item_ID you want to remove.") String itemID){ + private void sellAllDeleteCommand(CommandSender sender, + @Arg(name = "Item_ID", description = "The Item_ID you want to remove.") String itemID){ - if (!isEnabled()) return; + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (itemID == null){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); @@ -618,10 +767,6 @@ private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", d } itemID = itemID.toUpperCase(); - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_cant_find_item_config)); @@ -635,13 +780,17 @@ private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", d } } - @Command(identifier = "sellall edit", description = "SellAll edit command, edit an item of Shop.", + @Command(identifier = "sellall items edit", + description = "Edits an existing SellAll shop item.", permissions = "prison.admin", 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){ + @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 ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (itemID == null){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); @@ -654,10 +803,6 @@ private void sellAllEditCommand(CommandSender sender, return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_not_found)); @@ -674,7 +819,7 @@ private void sellAllEditCommand(CommandSender sender, } if (sellAllUtil.editPrice(blockAdd, value)){ - Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); + Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", " + value + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); } } catch (IllegalArgumentException ex){ @@ -682,22 +827,71 @@ private void sellAllEditCommand(CommandSender sender, } } - @Command(identifier = "sellall multiplier list", description = "SellAll multiplier command list", + + @Command(identifier = "sellall multiplier list", + description = "Lists all of the SellAll Rank multipliers", permissions = "prison.admin", onlyPlayers = false) - private void sellAllMultiplierCommand(CommandSender sender){ + private void sellAllMultiplierCommand(CommandSender sender, + @Wildcard(join=true) + @Arg(name = "options", + description = "Optionaly, you can control which ladder is displayed. By default, it's " + + "all ladders. Just use the ladder's name. You can also change the number of " + + "columns in the output by using 'cols=16', where the default is 10 columns. ") + String options ) { - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllMultiplierEnabled){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } + + if ( !PrisonRanks.getInstance().isEnabled() ) { + Output.get().sendWarn(sender, "Cannot use command `/sellall multiplier addLadder` since ranks are disabled" ); + return; + } + + int displayColumns = 10; + String ladderName = ""; + RankLadder rLadder = null; + + + // pull columns out of the options, if it has been specified: + String colsStr = extractParameter("cols=", options); + if ( colsStr != null ) { + options = options.replace( colsStr, "" ).trim(); + colsStr = colsStr.replace( "cols=", "" ).trim(); + + try { + displayColumns = Integer.parseInt( colsStr ); + } + catch ( NumberFormatException e ) { + // Not a valid int number: + } + } + + + // Check to see if the remaining options is a ladder name, if so, then only load that ladder: + if ( options.length() > 0 ) { + rLadder = PrisonRanks.getInstance().getLadderManager().getLadder( options ); + } + + + List ladders = new ArrayList<>(); + + if ( rLadder == null ) { + ladders = PrisonRanks.getInstance().getLadderManager().getLadders(); + } + else { + ladders.add( rLadder ); + } + + + // String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall multiplier help" ); // sender.dispatchCommand(registeredCmd); @@ -705,137 +899,365 @@ private void sellAllMultiplierCommand(CommandSender sender){ TreeMap mults = new TreeMap<>( sellAllUtil.getPrestigeMultipliers() ); // TreeMap items = new TreeMap<>( sellAllUtil.getSellAllBlocks() ); - DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); Set keys = mults.keySet(); + // Need to calculate the maxLenVal so we can properly space all columns: int maxLenKey = 0; int maxLenVal = 0; for ( String key : keys ) { if ( key.length() > maxLenKey ) { maxLenKey = key.length(); } - String val = fFmt.format( mults.get( key ) ); + String val = dFmt.format( mults.get( key ) ); if ( val.length() > maxLenVal ) { maxLenVal = val.length(); } } + String multiplierLayout = "%-" + maxLenKey + "s %" + maxLenVal + "s"; - ChatDisplay chatDisplay = new ChatDisplay("&bSellall Prestige Multipliers list: &3(&b" + keys.size() + "&3)" ); + ChatDisplay chatDisplay = new ChatDisplay("&bSellall Rank Multipliers list: &3(&b" + keys.size() + "&3)" ); - int lines = 0; - int columns = 0; - StringBuilder sb = new StringBuilder(); - for ( String key : keys ) { -// boolean first = sb.length() == 0; - Double cost = mults.get( key ); - - if ( columns++ > 0 ) { - sb.append( " " ); - } - - sb.append( String.format( "%-" + maxLenKey + "s %" + maxLenVal + "s", - key, fFmt.format( cost ) ) ); -// sb.append( String.format( "%-" + maxLenKey + "s %" + maxLenVal + "s %-" + maxLenCode + "s", -// key.toString(), fFmt.format( cost ), key.name() ) ); - - if ( columns > 4 ) { - chatDisplay.addText( sb.toString() ); - - if ( ++lines % 10 == 0 && lines > 1 ) { - chatDisplay.addText( " " ); - } - - sb.setLength( 0 ); - columns = 0; - } - } - if ( sb.length() > 0 ) { - chatDisplay.addText( sb.toString() ); - } - - chatDisplay.send( sender ); + for (RankLadder ladder : ladders ) { + + StringBuilder sb = new StringBuilder(); + int lines = 0; + int columns = 0; + for ( Rank rank : ladder.getRanks() ) { + String key = rank.getName(); + + if ( mults.containsKey( key ) ) { + + if ( lines == 0 && sb.length() == 0 ) { + chatDisplay.addText( "&3Ladder: &7%s &3Ranks: &7%s", + ladder.getName(), + iFmt.format( ladder.getRanks().size() )); + } + + Double cost = mults.get( key ); + + if ( columns++ > 0 ) { + sb.append( " " ); + } + + sb.append( String.format( multiplierLayout, + key, dFmt.format( cost ) ) ); + + if ( columns >= displayColumns ) { + chatDisplay.addText( sb.toString() ); + + if ( ++lines % 10 == 0 && lines > 1 ) { + chatDisplay.addText( " " ); + } + + sb.setLength( 0 ); + columns = 0; + } + + } + } + if ( sb.length() > 0 ) { + chatDisplay.addText( sb.toString() ); + } + + } +// int columns = 0; +// for ( String key : keys ) { +//// boolean first = sb.length() == 0; +// +// Double cost = mults.get( key ); +// +// if ( columns++ > 0 ) { +// sb.append( " " ); +// } +// +// sb.append( String.format( "%-" + maxLenKey + "s %" + maxLenVal + "s", +// key, fFmt.format( cost ) ) ); +//// sb.append( String.format( "%-" + maxLenKey + "s %" + maxLenVal + "s %-" + maxLenCode + "s", +//// key.toString(), fFmt.format( cost ), key.name() ) ); +// +// if ( columns > 7 ) { +// chatDisplay.addText( sb.toString() ); +// +// if ( ++lines % 10 == 0 && lines > 1 ) { +// chatDisplay.addText( " " ); +// } +// +// sb.setLength( 0 ); +// columns = 0; +// } +// } +// if ( sb.length() > 0 ) { +// chatDisplay.addText( sb.toString() ); +// } + chatDisplay.send( sender ); + } + private String extractParameter( String key, String options ) { + return extractParameter( key, options, true ); + } + private String extractParameter( String key, String options, boolean tryLowerCase ) { + String results = null; + int idx = options.indexOf( key ); + if ( idx != -1 ) { + int idxEnd = options.indexOf( " ", idx ); + if ( idxEnd == -1 ) { + idxEnd = options.length(); + } + results = options.substring( idx, idxEnd ); + } + else if ( tryLowerCase ) { + // try again, but lowercase the key + results = extractParameter( key.toLowerCase(), options, false ); + } + return results; + } - @Command(identifier = "sellall multiplier add", description = "SellAll add a multiplier. Permission multipliers for player's prison.sellall.multiplier., example prison.sellall.multiplier.2 will add a 2x multiplier," + - "There's also another kind of Multiplier called permission multipliers, they're permissions that you can give to players to give them a multiplier, remember that their format is prison.sellall.multiplier.2 (for example), and this example will give you a " + - "total of 3x multiplier (1x default + 2x permission = 3x).", + @Command(identifier = "sellall multiplier add", + description = "Add a sellall multiplier based upon the player's rank. " + + "All ranks that a player has, could have their own multiplier, that can " + + "be combined to help the player increase the value of what they are selling. " + + "These multipliers will be combined with all other player mulitpliers to " + + "adjust the sales price within sellall. Multipliers can be from these " + + "rank multipliers, and also from permission multipliers. " + + "All players start off with a default value of a multiplier with a value of 1, which " + + "equates to 100% of what they sell: no loss and no gain. From there, multipliers that " + + "you give to players can be integers, or doubles. They can be greater than 1, or less than " + + "1, or even negative. All multipliers are added together to provide the player's total " + + "amount. " + + "Permission multipliers for player's `prison.sellall.multiplier.`, " + + "example `prison.sellall.multiplier.2` will add a 2x multiplier. " + + "The multiplier values do not have to integers, but can be less than one, or " + + "doubles. " + + "There's also another kind of Multiplier called permission multipliers, they're permissions " + + "that you can give to players to give them a multiplier, remember that their format is " + + "'prison.sellall.multiplier.2.5' (for example), and this example will give you a " + + "total of 3.5x multiplier (1x default + 2.5x permission = 3.5x).", permissions = "prison.admin", 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){ + @Arg(name = "rank", description = "The rank name for the multiplier.") String rank, + @Arg(name = "multiplier", description = "Multiplier value.") Double multiplier) { - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllMultiplierEnabled){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } - if (sellAllUtil.addPrestigeMultiplier(prestige, multiplier)){ + if (sellAllUtil.addSellallRankMultiplier(rank, multiplier)){ Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_add_success)); } else { - Output.get().sendInfo( sender, "Failed to add sellall prestige multiplier." ); + Output.get().sendInfo( sender, "Failed to add sellall rank multiplier." ); } } - @Command(identifier = "sellall multiplier delete", description = "SellAll delete a multiplier.", + @Command(identifier = "sellall multiplier delete", + description = "Remove a SellAll rank multiplier.", permissions = "prison.admin", onlyPlayers = false) private void sellAllDeleteMultiplierCommand(CommandSender sender, - @Arg(name = "Prestige", description = "Prestige hooked to the multiplier.") String prestige){ + @Arg(name = "Rank", description = "The rank name of the multiplier.") String rank){ - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllMultiplierEnabled){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } - if (prestige == null){ + if (rank == null){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_command_wrong_format)); return; } - if (sellAllUtil.sellAllConfig.getConfigurationSection("Multiplier." + prestige) == null){ - Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_cant_find) + " [" + prestige + "]"); + if (sellAllUtil.sellAllConfig.getConfigurationSection("Multiplier." + rank) == null){ + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_cant_find) + " [" + rank + "]"); return; } - if (sellAllUtil.removePrestigeMultiplier(prestige)){ + if (sellAllUtil.removeSellallRankMultiplier(rank)){ Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_delete_success)); } } + + + + + @Command(identifier = "sellall multiplier deleteLadder", + description = "Deletes all SellAll Rank multipliers for a ladder.", + permissions = "prison.admin", onlyPlayers = false) + private void sellAllMultiplierDeleteLadderCommand( + CommandSender sender, + @Arg(name = "ladder", + description = "All ranks with multipliers for this ladder will be removed.") String ladderName + + ) { + + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); - @Command(identifier = "sellall Trigger", - description = "Toggle SellAll Shift+Right Click on a tool to trigger the /sellall sell command, " - + "true -> Enabled or False -> Disabled.", + if (!sellAllUtil.isSellAllMultiplierEnabled){ + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); + return; + } + + if ( !PrisonRanks.getInstance().isEnabled() ) { + Output.get().sendWarn(sender, "Cannot use command `/sellall multiplier deleteLadder` since ranks are disabled" ); + return; + } + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); + + + if ( ladder == null ) { + Output.get().sendWarn(sender, + "A ladder with the name of '%s' does not exist. Use '/ranks ladder list' " + + "to find the correct ladder name.", ladderName ); + + return; + } + + DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); + + int removed = 0; + for (Rank rank : ladder.getRanks() ) { + + if (sellAllUtil.removeSellallRankMultiplier( rank.getName() )) { + removed++; + } + } + + sender.sendMessage( + String.format( + "For ladder %s, there were %s multipliers removed.", + ladderName, iFmt.format(removed)) ); + + } + + + + @Command(identifier = "sellall multiplier addLadder", + description = "Adds multipliers for all ranks on the ladder. " + + "If they already exist, they will be replaced. The formula used to " + + "calculate the multiplier is " + + "'multiplier = baseMultiplier + ((rankPosition - 1) * rankMultiplier)'. " + + "Example: '/sellall multiplier addLadder presetiges 1.0 0.1' will result in " + + "p1=1.0 p2=1.1 p3=1.2 p4=1.3 etc...", + permissions = "prison.admin", onlyPlayers = false) + private void sellAllMultiplierAddLadderCommand( + CommandSender sender, + @Arg(name = "ladder", + def = "prestiges", + description = "Add multipliers for all ranks on this ladder. " + + "If multipliers already exist, they will be replaced.") + String ladderName, + @Arg(name = "baseMultiplier", + def = "1.0", + description = "The baseMultiplier that will have the rank's " + + "position multiplier added to it.") + double baseMultiplier, + @Arg(name = "rankMultiplier", + def = "0.1", + description = "The multiplier applied to the rank position.") + double rankMultiplier + + ) { + + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (!sellAllUtil.isSellAllMultiplierEnabled){ + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); + return; + } + + if ( !PrisonRanks.getInstance().isEnabled() ) { + Output.get().sendWarn(sender, "Cannot use command `/sellall multiplier addLadder` since ranks are disabled" ); + return; + } + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); + + + if ( ladder == null ) { + Output.get().sendWarn(sender, + "A ladder with the name of '%s' does not exist. Use '/ranks ladder list' " + + "to find the correct ladder name.", ladderName ); + + return; + } + + DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); + + int added = 0; + int failed = 0; + for (Rank rank : ladder.getRanks() ) { + + int rankPos = rank.getPosition(); + + double multi = baseMultiplier + (rankPos * rankMultiplier); + + if ( sellAllUtil.addSellallRankMultiplier(rank.getName(), multi) ) { + // No message should be sent for each rank, since there could be thousands of prestige ranks + added++; + } + else { + failed++; + } + + } + + sender.sendMessage( + String.format( + "For ladder %s, there were %s multipliers added, and %s failed to be added.", + ladderName, + iFmt.format(added), + iFmt.format(failed) + ) ); + + } + + + + + @Command(identifier = "sellall set trigger", + description = "Toggle SellAll trigger to enable/disable the Shift+Right Clicking " + + "on a tool to trigger the `/sellall sell` command " + + "true = enable, false = disable. " + + "[true false].", permissions = "prison.admin", onlyPlayers = false) private void sellAllToolsTriggerToggle(CommandSender sender, - @Arg(name = "Boolean", description = "Enable or disable", def = "null") String enable){ + @Arg(name = "Boolean", description = "Enable or disable", def = "true") String enable){ - if (!isEnabled()) return; + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (enable.equalsIgnoreCase("null")){ - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall toolsTrigger help" ); - sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall toolsTrigger help"); +// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall toolsTrigger help" ); +// sender.dispatchCommand(registeredCmd); return; } @@ -844,10 +1266,6 @@ private void sellAllToolsTriggerToggle(CommandSender sender, return; } - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ - return; - } boolean enableInput = getBoolean(enable); if (sellAllUtil.isSellAllItemTriggerEnabled == enableInput) { @@ -868,18 +1286,16 @@ private void sellAllToolsTriggerToggle(CommandSender sender, } } - @Command(identifier = "sellall Trigger add", + @Command(identifier = "sellall set trigger add", description = "Add an Item to trigger the Shift+Right Click -> /sellall sell command.", permissions = "prison.admin", onlyPlayers = false) private void sellAllTriggerAdd(CommandSender sender, @Arg(name = "Item", description = "Item name") String itemID){ - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllItemTriggerEnabled){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_is_disabled)); @@ -909,18 +1325,16 @@ private void sellAllTriggerAdd(CommandSender sender, } } - @Command(identifier = "sellall Trigger delete", + @Command(identifier = "sellall set trigger delete", description = "Delete an Item from the Shift+Right Click trigger -> /sellall sell command.", permissions = "prison.admin", onlyPlayers = false) private void sellAllTriggerDelete(CommandSender sender, @Arg(name = "Item", description = "Item name") String itemID){ - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if (!isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllItemTriggerEnabled){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_is_disabled)); @@ -949,7 +1363,9 @@ private void sellAllTriggerDelete(CommandSender sender, } } - @Command(identifier = "sellall setdefault", description = "SellAll default values ready to go.", + @Command(identifier = "sellall items setdefaults", + description = "This command will setup all of the shop items with " + + "the SellAll default items.", permissions = "prison.admin", onlyPlayers = false) private void sellAllSetDefaultCommand(CommandSender sender){ @@ -971,29 +1387,27 @@ private void sellAllSetDefaultCommand(CommandSender sender){ permissions = "prison.admin", onlyPlayers = false) private void sellAllListItems( CommandSender sender ) { - if (!isEnabled()) return; - - SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil == null){ + if ( !isEnabled() || !SpigotPrison.getInstance().isSellAllEnabled() ){ return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); - TreeMap items = new TreeMap<>( sellAllUtil.getSellAllBlocks() ); + TreeMap items = new TreeMap<>( sellAllUtil.getSellAllItems() ); DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); - Set keys = items.keySet(); + Set keys = items.keySet(); int maxLenKey = 0; int maxLenVal = 0; int maxLenCode = 0; - for ( XMaterial key : keys ) { - if ( key.toString().length() > maxLenKey ) { - maxLenKey = key.toString().length(); - } - if ( key.name().length() > maxLenCode ) { - maxLenCode = key.name().length(); + for ( String key : keys ) { +// if ( key.toString().length() > maxLenKey ) { +// maxLenKey = key.toString().length(); +// } + if ( key.length() > maxLenCode ) { + maxLenCode = key.length(); } - String val = fFmt.format( items.get( key ) ); + String val = fFmt.format( items.get( key ).getSalePrice() ); if ( val.length() > maxLenVal ) { maxLenVal = val.length(); } @@ -1004,17 +1418,17 @@ private void sellAllListItems( CommandSender sender ) { int lines = 0; StringBuilder sb = new StringBuilder(); - for ( XMaterial key : keys ) { + for ( String key : keys ) { boolean first = sb.length() == 0; - Double cost = items.get( key ); + Double cost = items.get( key ).getSalePrice(); if ( !first ) { sb.append( " " ); } sb.append( String.format( "%-" + maxLenCode + "s %" + maxLenVal + "s", - key.name(), fFmt.format( cost ) ) ); + key, fFmt.format( cost ) ) ); // sb.append( String.format( "%-" + maxLenKey + "s %" + maxLenVal + "s %-" + maxLenCode + "s", // key.toString(), fFmt.format( cost ), key.name() ) ); 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 dc3bc50ad..8b1be84a3 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 @@ -70,4 +70,37 @@ public interface CompatibilityBlocks public int getMaxY(); + + + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + public int getCustomModelData( SpigotItemStack itemStack ); + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + public int getCustomModelData( ItemStack itemStack ); + + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + public void setCustomModelData( SpigotItemStack itemStack, int customModelData ); + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + public void setCustomModelData( ItemStack itemStack, int customModelData ); + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java index 6199c23c5..ce98af5fa 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java @@ -27,7 +27,7 @@ private static synchronized void setup() { if ( bukkitVersion == null ) { - results = new Spigot113(); + results = new Spigot_1_13(); } else { @@ -35,19 +35,23 @@ private static synchronized void setup() { if ( svData.compareTo( new BluesSemanticVersionData( "1.9.0" ) ) < 0 ) { - results = new Spigot18(); + results = new Spigot_1_8(); } else if ( svData.compareTo( new BluesSemanticVersionData( "1.13.0" ) ) < 0 ) { - results = new Spigot19(); + results = new Spigot_1_9(); + } + else if ( svData.compareTo( new BluesSemanticVersionData( "1.14.0" ) ) < 0 ) { + + results = new Spigot_1_13(); } else if ( svData.compareTo( new BluesSemanticVersionData( "1.18.0" ) ) < 0 ) { - results = new Spigot113(); + results = new Spigot_1_14(); } else { - results = new Spigot118(); + results = new Spigot_1_18(); } } 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/Spigot_1_13.java similarity index 98% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13.java index e0d296255..86c3642a8 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/Spigot_1_13.java @@ -12,8 +12,8 @@ import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; -public class Spigot113 - extends Spigot113GUI +public class Spigot_1_13 + extends Spigot_1_13_GUI implements Compatibility { @Override 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/Spigot_1_13_Blocks.java similarity index 99% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_Blocks.java index b27af2194..f0d86452b 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/Spigot_1_13_Blocks.java @@ -19,8 +19,8 @@ import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.Location; -public abstract class Spigot113Blocks - extends Spigot19Player +public abstract class Spigot_1_13_Blocks + extends Spigot_1_9_Player implements CompatibilityBlocks { // @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113GUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_GUI.java similarity index 77% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113GUI.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_GUI.java index 62acc09b9..94ad8c1c4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113GUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_GUI.java @@ -2,8 +2,8 @@ import org.bukkit.event.inventory.InventoryEvent; -public abstract class Spigot113GUI - extends Spigot113Blocks +public abstract class Spigot_1_13_GUI + extends Spigot_1_13_Blocks implements CompatibilityGUI { @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14.java new file mode 100644 index 000000000..754779bd1 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14.java @@ -0,0 +1,6 @@ +package tech.mcprison.prison.spigot.compat; + +public class Spigot_1_14 + extends Spigot_1_14_Blocks { + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14_Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14_Blocks.java new file mode 100644 index 000000000..9a76d4372 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_14_Blocks.java @@ -0,0 +1,109 @@ +package tech.mcprison.prison.spigot.compat; + +import java.lang.reflect.Method; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import tech.mcprison.prison.spigot.block.SpigotItemStack; + +public class Spigot_1_14_Blocks + extends Spigot_1_13 + //implements CompatibilityBlocks +{ + + private static Method SET_CUSTOM_MODEL_DATA = null; + private static Method GET_CUSTOM_MODEL_DATA = null; + + static { + try { + SET_CUSTOM_MODEL_DATA = ItemMeta.class.getDeclaredMethod("setCustomModelData", Integer.class); + GET_CUSTOM_MODEL_DATA = ItemMeta.class.getDeclaredMethod("getCustomModelData"); + } + catch (NoSuchMethodException ex) { + ex.printStackTrace(); + } + } + + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public int getCustomModelData( SpigotItemStack itemStack ) { + return getCustomModelData( itemStack == null ? null : itemStack.getBukkitStack() ); + } + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public int getCustomModelData( ItemStack itemStack ) { + int results = 0; + + if ( itemStack != null ) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta != null) { + try { + Integer customModelData = (Integer) GET_CUSTOM_MODEL_DATA.invoke(meta); + + if ( customModelData != null ) { + results = customModelData.intValue(); + } + } + catch (ReflectiveOperationException ex ) { + ex.printStackTrace(); + } + catch ( ClassCastException ex ) { + ex.printStackTrace(); + } + } + itemStack.setItemMeta(meta); + } + + return results; + } + + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public void setCustomModelData( SpigotItemStack itemStack, int customModelData ) { + if ( itemStack != null ) { + setCustomModelData( itemStack.getBukkitStack(), customModelData); + } + } + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public void setCustomModelData( ItemStack itemStack, int customModelData ) { + + if ( itemStack != null ) { + ItemMeta meta = itemStack.getItemMeta(); + + if (meta != null) { + try { + + SET_CUSTOM_MODEL_DATA.invoke( meta, customModelData ); + } + catch (ReflectiveOperationException ex) { + ex.printStackTrace(); + } + } + itemStack.setItemMeta(meta); + } + + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot118.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java similarity index 72% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot118.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java index f4ef76aab..2ef9cb96b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot118.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java @@ -1,7 +1,8 @@ package tech.mcprison.prison.spigot.compat; -public class Spigot118 - extends Spigot113 +public class Spigot_1_18 + extends Spigot_1_14 + implements Compatibility { 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/Spigot_1_8.java similarity index 98% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8.java index 2c0f89864..ec7cffb74 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/Spigot_1_8.java @@ -33,8 +33,8 @@ /** * @author Faizaan A. Datoo */ -public class Spigot18 - extends Spigot18GUI +public class Spigot_1_8 + extends Spigot_1_8_GUI implements Compatibility { 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/Spigot_1_8_Blocks.java similarity index 93% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Blocks.java index 8594d6924..fbb1b65c6 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/Spigot_1_8_Blocks.java @@ -15,8 +15,8 @@ import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.Location; -public abstract class Spigot18Blocks - extends Spigot18Player +public abstract class Spigot_1_8_Blocks + extends Spigot_1_8_Player implements CompatibilityBlocks { @@ -275,10 +275,19 @@ public XMaterial getXMaterial( PrisonBlock prisonBlock ) { results = XMaterial.matchXMaterial( blockName ).orElse( null ); + // Convert items to their block representation: if ( results == XMaterial.MELON_SLICE && prisonBlock.getBlockName().equalsIgnoreCase( "melon" ) ) { results = XMaterial.MELON; } + else if ( results == XMaterial.BRICK && + prisonBlock.getBlockName().equalsIgnoreCase( "bricks" ) ) { + results = XMaterial.BRICKS; + } + else if ( results == XMaterial.BRICK && + prisonBlock.getBlockName().equalsIgnoreCase( "brick" ) ) { + results = XMaterial.BRICKS; + } putCachedXMaterial( prisonBlock, results ); } @@ -744,4 +753,51 @@ public int getMaxY() { return 255; } + + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public int getCustomModelData( SpigotItemStack itemStack ) { + return 0; + } + /** + * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public int getCustomModelData( ItemStack itemStack ) { + return 0; + } + + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public void setCustomModelData( SpigotItemStack itemStack, int customModelData ) { + if ( itemStack != null ) { + setCustomModelData( itemStack.getBukkitStack(), customModelData); + } + } + /** + * Not compatible with Spigot 1.8 through 1.13 so do nothing. + * Only available with 1.14 and higher. + * @param itemStack + * @return + */ + @Override + public void setCustomModelData( ItemStack itemStack, int customModelData ) { + + } + + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18GUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_GUI.java similarity index 80% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18GUI.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_GUI.java index 7a30037c2..a7a288b31 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18GUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_GUI.java @@ -2,8 +2,8 @@ import org.bukkit.event.inventory.InventoryEvent; -public abstract class Spigot18GUI - extends Spigot18Blocks +public abstract class Spigot_1_8_GUI + extends Spigot_1_8_Blocks implements CompatibilityGUI { @SuppressWarnings( "deprecation" ) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java similarity index 98% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java index 32de7241f..4e35f8fb6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java @@ -7,7 +7,7 @@ import tech.mcprison.prison.util.Text; -public abstract class Spigot18Player +public abstract class Spigot_1_8_Player extends CompatibilityCache implements CompatibilityPlayer { 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/Spigot_1_9.java similarity index 98% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9.java index 5b3a2e2d5..b6fb32c73 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/Spigot_1_9.java @@ -35,8 +35,8 @@ * * @author Faizaan A. Datoo */ -public class Spigot19 - extends Spigot19GUI +public class Spigot_1_9 + extends Spigot_1_9_GUI implements Compatibility { @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19GUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_GUI.java similarity index 80% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19GUI.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_GUI.java index 3268e52ad..92402b13f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19GUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_GUI.java @@ -2,8 +2,8 @@ import org.bukkit.event.inventory.InventoryEvent; -public class Spigot19GUI - extends Spigot19Player +public class Spigot_1_9_GUI + extends Spigot_1_9_Player implements CompatibilityGUI { @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java similarity index 96% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java rename to prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java index 370aa8045..ce90aca41 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java @@ -9,8 +9,8 @@ import tech.mcprison.prison.util.Text; -public abstract class Spigot19Player - extends Spigot18Blocks +public abstract class Spigot_1_9_Player + extends Spigot_1_8_Blocks { public void setMaxHealth( Player player, double maxHealth ) { 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 1335180ba..bdf924b1b 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 @@ -14,6 +14,8 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.spigot.SpigotPrison; /** @@ -220,6 +222,95 @@ else if ( conf.get( "Options.Mines.MaterialType.NoMineAccess" ) == null ) { changeCount++; } + + + if ( conf.get( "Options.Ranks.MaterialType" ) == null ) { + + if ( PrisonRanks.getInstance() != null ) { + + LinkedHashMap map = new LinkedHashMap<>(); + + map.put("NoRankAccess", XMaterial.REDSTONE_BLOCK.name() ); + + // Example to preset all ranks: Only do the first 10: + int count = 0; + for ( Rank rank : PrisonRanks.getInstance().getRankManager().getRanks() ) { + map.put( rank.getName(), XMaterial.TRIPWIRE_HOOK.name() ); + if ( ++count >= 10 ) { + break; + } + } + + conf.set("Options.Ranks.MaterialType", map); + changeCount++; + } + } + else if ( conf.get( "Options.Ranks.MaterialType.NoMineAccess" ) == null ) { + + String noMineAccess = XMaterial.REDSTONE_BLOCK.name(); + + conf.set("Options.Ranks.MaterialType.NoMineAccess", noMineAccess ); + changeCount++; + } + + + + if ( conf.get( "Options.Mines.GuiItemNameDefault" ) == null ) { + + String defaultName = "{mineTag}"; + + conf.set("Options.Mines.GuiItemNameDefault", defaultName ); + changeCount++; + } + + if ( conf.get( "Options.Mines.GuiItemNames" ) == null ) { + + if ( PrisonMines.getInstance() != null ) { + + LinkedHashMap map = new LinkedHashMap<>(); + + // Example to preset all mines: Only do the first 10: + int count = 0; + for ( Mine mine : PrisonMines.getInstance().getMineManager().getMines() ) { + map.put( mine.getName(), mine.getTag() ); + if ( ++count >= 10 ) { + break; + } + } + + conf.set("Options.Mines.GuiItemNames", map); + changeCount++; + } + } + + + if ( conf.get( "Options.Ranks.GuiItemNameDefault" ) == null ) { + + String defaultName = "{rankTag}"; + + conf.set("Options.Ranks.GuiItemNameDefault", defaultName ); + changeCount++; + } + if ( conf.get( "Options.Ranks.GuiItemNames" ) == null ) { + + if ( PrisonRanks.getInstance() != null ) { + + LinkedHashMap map = new LinkedHashMap<>(); + + // Example to preset all ranks: Only do the first 10: + int count = 0; + for ( Rank rank : PrisonRanks.getInstance().getRankManager().getRanks() ) { + map.put( rank.getName(), rank.getTag() ); + if ( ++count >= 10 ) { + break; + } + } + + conf.set("Options.Ranks.GuiItemNames", map); + changeCount++; + } + } + // Count and save if (changeCount > 0) { try { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomy.java new file mode 100644 index 000000000..0538d6682 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomy.java @@ -0,0 +1,240 @@ +package tech.mcprison.prison.spigot.economies; + +import tech.mcprison.prison.integration.EconomyCurrencyIntegration; +import tech.mcprison.prison.internal.Player; + +public class CoinsEngineEconomy + extends EconomyCurrencyIntegration { + + + private CoinsEngineEconomyWrapper wrapper = null; + private boolean availableAsAnAlternative = false; + + public CoinsEngineEconomy() { + super( "CoinsEngineEconomy", "CoinsEngineEconomy" ); + } + + /** + *

If GemsEconomy is registered, always hook this up because this may be needed + * to be used instead of the primary economy if they are using a custom currency. + *

+ */ + @Override + public void integrate() { + addDebugInfo( "1" ); + if ( isRegistered()) { + addDebugInfo( "2" ); + try { + addDebugInfo( "3" ); + this.wrapper = new CoinsEngineEconomyWrapper(); + addDebugInfo( "4" ); + } + catch ( java.lang.NoClassDefFoundError | Exception e ) { + addDebugInfo( "5:Exception:" + e.getMessage() ); + e.printStackTrace(); + } + } + addDebugInfo( "6" ); + } + + + @Override + public boolean supportedCurrency( String currencyName ) { + boolean supported = false; + + if ( wrapper != null ) { + supported = wrapper.supportedCurrency( currencyName ); + } + + return supported; + } + + @Override + public double getBalance(Player player) { + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player); + } + } + return amount; + } + + @Override + public double getBalance(Player player, String currencyName) { + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player, currencyName); + } + } + return amount; + } + + @Override + public boolean setBalance(Player player, double amount) { + boolean results = false; + + if ( wrapper != null ) { + synchronized ( wrapper ) { + + double bal = getBalance(player); + double remainder = amount - bal; + + if ( remainder > 0 ) { + wrapper.addBalance( player, remainder ); + } + else if ( remainder < 0 ) { + wrapper.withdraw( player, (remainder * -1) ); + } + double balResults = getBalance(player); + + results = balResults == amount; + } + } + return results; + } + + @Override + public boolean setBalance(Player player, double amount, String currencyName) { + boolean results = false; + + if ( wrapper != null ) { + + synchronized ( wrapper ) { + + double bal = getBalance(player, currencyName); + double remainder = amount - bal; + + if ( remainder > 0 ) { + wrapper.addBalance( player, remainder, currencyName ); + } + else if ( remainder < 0 ) { + wrapper.withdraw( player, (remainder * -1), currencyName ); + } + double balResults = getBalance(player, currencyName); + + results = balResults == amount; + } + } + return results; + } + + @Override + public boolean addBalance(Player player, double amount) { + boolean results = false; + + if ( wrapper != null ) { + + synchronized ( wrapper ) { + + double bal = getBalance(player); + wrapper.addBalance(player, amount); + double balResults = getBalance(player); + + results = balResults == amount + bal; + } + } + + return results; + } + + @Override + public boolean addBalance(Player player, double amount, String currencyName) { + boolean results = false; + + if ( wrapper != null ) { + + synchronized ( wrapper ) { + + double bal = getBalance(player, currencyName); + wrapper.addBalance(player, amount, currencyName); + double balResults = getBalance(player, currencyName); + + results = balResults == amount + bal; + } + } + + return results; + } + + @Override + public boolean removeBalance(Player player, double amount) { + boolean results = false; + + if ( wrapper != null ) { + synchronized ( wrapper ) { + + double bal = getBalance(player); + wrapper.withdraw(player, amount); + double balResults = getBalance(player); + + results = balResults == bal - amount; + } + } + + return results; + } + + @Override + public boolean removeBalance(Player player, double amount, String currencyName) { + boolean results = false; + + if ( wrapper != null ) { + synchronized ( wrapper ) { + + double bal = getBalance(player, currencyName); + wrapper.withdraw(player, amount, currencyName); + double balResults = getBalance(player, currencyName); + + results = balResults == bal - amount; + } + } + + return results; + } + + @Override + public boolean canAfford(Player player, double amount) { + boolean results = false; + if ( wrapper != null ) { + results = getBalance(player) >= amount; + } + return results; + } + + @Override + public boolean canAfford(Player player, double amount, String currencyName) { + boolean results = false; + if ( wrapper != null ) { + results = getBalance(player, currencyName) >= amount; + } + return results; + } + + @Override + public boolean hasIntegrated() { + return wrapper != null && wrapper.isEnabled(); + } + + @Override + public void disableIntegration() { + wrapper = null; + } + + @Override + public String getDisplayName() + { + return super.getDisplayName() + + ( availableAsAnAlternative ? " (disabled)" : ""); + } + + @Override + public String getPluginSourceURL() { + return "https://www.spigotmc.org/resources/coinsengine-economy-and-virtual-currencies.84121/"; + } + + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomyWrapper.java new file mode 100644 index 000000000..e1d248e57 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/CoinsEngineEconomyWrapper.java @@ -0,0 +1,108 @@ +package tech.mcprison.prison.spigot.economies; + +import su.nightexpress.coinsengine.api.CoinsEngineAPI; +import su.nightexpress.coinsengine.api.currency.Currency; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.game.SpigotPlayer; + +public class CoinsEngineEconomyWrapper { + + private CoinsEngineAPI economy; + + public CoinsEngineEconomyWrapper() { + super(); + + + try { + this.economy = new CoinsEngineAPI(); + } + catch (Exception e) { + // If CoinsEngineAPI does not exist, then ignore this exception: + } + + + } + + + public boolean isEnabled() { + return economy != null; + } + + public boolean supportedCurrency( String currencyName ) { + boolean supported = ( getCurrency( currencyName ) != null ); + + return supported; + } + + + public Currency getCurrency( String currencyNamme ) { + return CoinsEngineAPI.getCurrency( currencyNamme ); + } + + + public double getBalance(Player player) { + + Output.get().logWarn( "CoinsEngineEconomy getBalance() - Fail: MUST include a currencyName."); + return getBalance(player, null); + } + + public double getBalance(Player player, String currencyName) { + double results = 0; + if (economy != null && player instanceof SpigotPlayer ) { + + org.bukkit.entity.Player sPlayer = ((SpigotPlayer) player).getWrapper(); + + Currency currency = getCurrency( currencyName ); + if ( currency != null && sPlayer != null) { + + results = CoinsEngineAPI.getBalance( sPlayer, currency ); + } + } + return results; + } + + public void addBalance(Player player, double amount) { + + Output.get().logWarn( "CoinsEngineEconomy addBalance() - Fail: MUST include a currencyName."); + addBalance(player, amount, null); + } + + public void addBalance(Player player, double amount, String currencyName) { + + if (economy != null && player instanceof SpigotPlayer ) { + + org.bukkit.entity.Player sPlayer = ((SpigotPlayer) player).getWrapper(); + + Currency currency = getCurrency( currencyName ); + if ( currency != null && sPlayer != null) { + + CoinsEngineAPI.addBalance( sPlayer, currency, amount ); + } + } + } + + + public void withdraw(Player player, double amount) { + + Output.get().logWarn( "CoinsEngineEconomy withdraw() - Fail: MUST include a currencyName."); + withdraw(player, amount, null); + } + + public void withdraw(Player player, double amount, String currencyName) { + + + if (economy != null && player instanceof SpigotPlayer ) { + + org.bukkit.entity.Player sPlayer = ((SpigotPlayer) player).getWrapper(); + + Currency currency = getCurrency( currencyName ); + if ( currency != null && sPlayer != null) { + + CoinsEngineAPI.removeBalance( sPlayer, currency, amount ); + } + } + + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java index 26bbb66d4..8e4b0d890 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java @@ -61,8 +61,16 @@ public String getName() { return bukkitSender.getName(); } + /** + *

This function will dispatch a command and run it as command sender. + * But before it is ran, this function looks up within the Prison command handler + * to see if it's commands have been remapped to another command, and if it has, + * it then uses the mapped command. + *

+ */ @Override public void dispatchCommand(String command) { - Bukkit.getServer().dispatchCommand(bukkitSender, command); + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( command ); + Bukkit.getServer().dispatchCommand(bukkitSender, registeredCmd); } @Override public boolean doesSupportColors() { @@ -91,7 +99,8 @@ public void sendMessage(String[] messages) { } } - @Override public void sendRaw(String json) { + @Override + public void sendRaw(String json) { if (bukkitSender instanceof org.bukkit.entity.Player) { json = Text.translateAmpColorCodes(json); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + bukkitSender.getName() + " " + json); 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 d1dd9ed9d..453d6bcc6 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 @@ -46,13 +46,16 @@ import tech.mcprison.prison.internal.inventory.Inventory; import tech.mcprison.prison.internal.scoreboard.Scoreboard; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.spigot.scoreboard.SpigotScoreboard; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.utils.tasks.PlayerMessagingTask; import tech.mcprison.prison.util.Gamemode; import tech.mcprison.prison.util.Location; @@ -62,7 +65,7 @@ */ public class SpigotPlayer extends SpigotCommandSender - implements Player { + implements Player, Comparable { private RankPlayer rankPlayer; @@ -230,7 +233,10 @@ public org.bukkit.entity.Player getWrapper() { @Override public Inventory getInventory() { - return new SpigotPlayerInventory(getWrapper().getInventory()); + return getSpigotPlayerInventory(); + } + public SpigotPlayerInventory getSpigotPlayerInventory() { + return new SpigotPlayerInventory(getWrapper().getInventory()); } @Override public void updateInventory() { @@ -303,6 +309,12 @@ public Inventory getInventory() { // return results; // } + @Override + public int compareTo( SpigotPlayer sPlayer) { + return getName().compareTo( sPlayer.getName() ); + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -835,5 +847,96 @@ public boolean isInventoryFull() { return results; } + /** + *

This function will identify if the player is able to have + * autosell enabled for them. This will take in to consideration + * global settings, and also if they have toggled off their + * autosell capabilities ('/sellall autoSellToggle`). + *

+ * + * @return + */ + public boolean isAutoSellEnabled() { + return isAutoSellEnabled( null ); + } + public boolean isAutoSellEnabled( StringBuilder debugInfo ) { + boolean results = false; + + if ( SpigotPrison.getInstance().isSellAllEnabled() ) { + + boolean isAutoSellPerUserToggleable = SellAllUtil.get().isAutoSellPerUserToggleable; + + boolean isPlayerAutoSellTurnedOff = isAutoSellPerUserToggleable && + !SellAllUtil.get().isSellallPlayerUserToggleEnabled( + getWrapper() ); + + if ( debugInfo != null && isPlayerAutoSellTurnedOff ) { + debugInfo.append( Output.get().getColorCodeWarning() ); + debugInfo.append( "(Player toggled off autosell) " ); + debugInfo.append( Output.get().getColorCodeDebug() ); + } + + // This will return true (allow autosell) unless players can toggle autosell and they turned it off: + // This is to be used with other auto sell setting, but never on it's own: + results = !isAutoSellPerUserToggleable || + isPlayerAutoSellTurnedOff; + } + + return results; + } + + + /** + *

This will check to see if the player has the perms enabled + * for autosell. + *

+ * + *

If the function 'isAutoSellEnabled()' has already + * been called, you can also pass that in as a parameter so it does + * not have to be recalculated. + *

+ * + * @return + */ + public boolean isAutoSellByPermEnabled() { + return isAutoSellByPermEnabled( isAutoSellEnabled() ); + } + + /** + *

This will check to see if the player has the perms enabled + * for autosell. + *

+ * + *

If the function 'isAutoSellEnabled()' has already + * been called, you can also pass that in as a parameter so it does + * not have to be recalculated. + *

+ * + * @param isPlayerAutosellEnabled + * @return + */ + public boolean isAutoSellByPermEnabled( boolean isPlayerAutosellEnabled ) { + + boolean autoSellByPerm = false; + + AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); + + boolean isSellallEnabled = SpigotPrison.getInstance().isSellAllEnabled(); + + if ( isSellallEnabled && isPlayerAutosellEnabled && !isOp() ) { + + String perm = afw.getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ); + + autoSellByPerm = + + afw.isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && + !"disable".equalsIgnoreCase( perm ) && + !"false".equalsIgnoreCase( perm ) && + hasPermission( perm ); + } + + + return autoSellByPerm; + } } 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 ba981046d..cfe91068e 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 @@ -700,9 +700,11 @@ else if ( SpigotGUIMenuTools.getInstance().processGUIPage( p, title, e ) ) { if (parts[0].equalsIgnoreCase("Backpack")){ if (e.isRightClick() && e.isShiftClick()){ if (parts[2].equalsIgnoreCase("default")){ - Bukkit.dispatchCommand(p, "backpack delete " + parts[1]); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "backpack delete " + parts[1] )); } else { - Bukkit.dispatchCommand(p, "backpack delete " + parts[1] + " " + parts[2]); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "backpack delete " + parts[1] + " " + parts[2] )); } p.closeInventory(); BackpacksAdminListGUI gui = new BackpacksAdminListGUI(p, parts[1]); @@ -766,7 +768,8 @@ else if ( SpigotGUIMenuTools.getInstance().processGUIPage( p, title, e ) ) { // } // // if ( isPageAction && command != null ) { -// Bukkit.dispatchCommand(p, command); +// Bukkit.dispatchCommand(p, +// Prison.get().getCommandHandler().findRegisteredCommand( command )); // // } // } @@ -833,7 +836,8 @@ private void backpacksList(Player p, String buttonNameMain, String[] parts) { } String finalID = String.valueOf(freeID); - Bukkit.dispatchCommand(p, "gui backpack " + finalID); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "gui backpack " + finalID )); } } else if (buttonNameMain.equalsIgnoreCase("Backpack")){ @@ -1321,7 +1325,8 @@ private boolean guiConditions(InventoryClickEvent e, Player p) { private void prisonSetupConfirmGUI(InventoryClickEvent e, Player p, String[] parts) { if (parts[0].equalsIgnoreCase("Confirm:")){ - Bukkit.dispatchCommand(p, "ranks autoConfigure"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "ranks autoConfigure" )); } else if (parts[0].equalsIgnoreCase("Cancel:")){ Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_event_cancelled)); } @@ -1406,7 +1411,9 @@ private void mineBlockPercentage(InventoryClickEvent e, Player p, String[] parts // Execute the command if (part4 != null) { - Bukkit.dispatchCommand(p, "mines block set " + part2 + " " + part3 + " " + part4); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines block set " + part2 + " " + part3 + " " + part4 )); } // Cancel the event @@ -1524,7 +1531,9 @@ private void sellAllItemValue(InventoryClickEvent e, Player p, String[] parts) { if (e.isLeftClick()){ // Execute the command - Bukkit.dispatchCommand(p,"sellall edit " + part2 + " " + part3); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "sellall edit " + part2 + " " + part3 )); // Close the inventory p.closeInventory(); @@ -1731,7 +1740,8 @@ private void laddersGUI(InventoryClickEvent e, Player p, String buttonNameMain, else { // Execute the command - Bukkit.dispatchCommand(p, "ranks ladder delete " + buttonNameMain); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "ranks ladder delete " + buttonNameMain )); e.setCancelled(true); p.closeInventory(); SpigotLaddersGUI gui = new SpigotLaddersGUI(p, 1, "gui ladders", "gui" ); @@ -1776,7 +1786,8 @@ private void ranksGUI(InventoryClickEvent e, Player p, String buttonNameMain, St RankLadder rLadder = rank.getLadder(); // Execute the command. - Bukkit.dispatchCommand(p, "ranks delete " + buttonNameMain); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "ranks delete " + buttonNameMain )); e.setCancelled(true); p.closeInventory(); SpigotRanksGUI gui = new SpigotRanksGUI( p, rLadder, 1, "gui admin ranks", "gui" ); @@ -1802,7 +1813,8 @@ private void playerPrestigesGUI(InventoryClickEvent e, Player p, String buttonNa // Close the inventory. p.closeInventory(); // Execute the command. - Bukkit.dispatchCommand(p, "prestige"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "prestige" )); } // Cancel the event. @@ -1931,7 +1943,9 @@ private void playerRanksGUI(InventoryClickEvent e, Player p, String buttonNameMa // Check the buttonName and do the actions. String message = Text.stripColor( messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup) ); if (buttonNameMain.equals(SpigotPrison.format( message ))){ - Bukkit.dispatchCommand(p, "rankup " + guiConfig.getString("Options.Ranks.Ladder")); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "rankup " + guiConfig.getString("Options.Ranks.Ladder" ))); p.closeInventory(); } @@ -1945,7 +1959,8 @@ private void rankUPCommandsGUI(InventoryClickEvent e, Player p, String buttonNam if (e.isShiftClick() && e.isRightClick()) { // Execute the command. - Bukkit.dispatchCommand(p, "ranks command remove " + buttonNameMain); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "ranks command remove " + buttonNameMain )); // Cancel the event. e.setCancelled(true); // Close the inventory. @@ -1980,7 +1995,8 @@ private void rankPriceGUI(InventoryClickEvent e, Player p, String[] parts) { if (e.isLeftClick()){ // Execute the command. - Bukkit.dispatchCommand(p,"ranks set cost " + part2 + " " + part3); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "ranks set cost " + part2 + " " + part3 )); // Close the inventory. p.closeInventory(); @@ -2080,7 +2096,8 @@ private void minesGUI(InventoryClickEvent e, Player p, String buttonNameMain, St // Check the clicks. if (e.isShiftClick() && e.isRightClick()) { // Execute the command. - Bukkit.dispatchCommand(p, "mines delete " + buttonNameMain); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines delete " + buttonNameMain )); // Cancel the event. e.setCancelled(true); // Close the inventory. @@ -2125,10 +2142,14 @@ private void playerMinesGUI(Player p, InventoryClickEvent e) { if (errorHasMiningPermission && (p.hasPermission(permission + mineName) || p.hasPermission(permission.substring(0, permission.length() - 1)))){ - Bukkit.dispatchCommand(p, SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName)); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName ))); } else if (hasMiningPermission || p.hasPermission(permission + mineName) || p.hasPermission(permission.substring(0, permission.length() - 1))){ - Bukkit.dispatchCommand(p, SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName)); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName ))); } } } @@ -2155,13 +2176,16 @@ private void mineInfoGUI(InventoryClickEvent e, Player p, String[] parts) { // Check the clickType and do the actions. if (e.isLeftClick()) { // Execute the command. - Bukkit.dispatchCommand(p, "mines reset " + mineName); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines reset " + mineName )); } else if (e.isRightClick()){ // Execute the command. - Bukkit.dispatchCommand(p, "mines set skipReset " + mineName); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines set skipReset " + mineName )); } else if (e.isRightClick() && e.isShiftClick()){ // Execute the command. - Bukkit.dispatchCommand(p, "mines set zeroBlockResetDelay " + mineName); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines set zeroBlockResetDelay " + mineName )); } // Cancel the event. @@ -2173,7 +2197,8 @@ private void mineInfoGUI(InventoryClickEvent e, Player p, String[] parts) { case "Mine_Spawn:": // Execute the command. - Bukkit.dispatchCommand(p, "mines set spawn " + mineName); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines set spawn " + mineName )); // Cancel the event. e.setCancelled(true); @@ -2195,7 +2220,8 @@ private void mineInfoGUI(InventoryClickEvent e, Player p, String[] parts) { p.closeInventory(); // Execute the Command. - Bukkit.dispatchCommand(p, "mines tp " + mineName); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines tp " + mineName )); break; @@ -2245,7 +2271,8 @@ private void minesDeleteGUI(Player p, String[] parts) { if (buttonname.equals("Confirm:")) { // Confirm - Bukkit.dispatchCommand(p, "mines delete " + mineName + " confirm"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines delete " + mineName + " confirm" )); // Close the Inventory p.closeInventory(); @@ -2254,7 +2281,8 @@ private void minesDeleteGUI(Player p, String[] parts) { } else if (buttonname.equals("Cancel:")) { // Cancel - Bukkit.dispatchCommand(p, "mines delete " + mineName + " cancel"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( "mines delete " + mineName + " cancel" )); // Close the inventory p.closeInventory(); @@ -2281,7 +2309,9 @@ private void blocksGUI(InventoryClickEvent e, Player p, String[] parts) { if (e.isShiftClick() && e.isRightClick()) { // Execute the command - Bukkit.dispatchCommand(p, "mines block remove " + mineName + " " + buttonname); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines block remove " + mineName + " " + buttonname )); // Cancel the event e.setCancelled(true); @@ -2330,7 +2360,9 @@ private void resetTimeGUI(InventoryClickEvent e, Player p, String[] parts) { if (e.isLeftClick()){ // Execute the command - Bukkit.dispatchCommand(p,"mines set resettime " + part2 + " " + part3); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines set resettime " + part2 + " " + part3 )); // Cancel the event e.setCancelled(true); @@ -2445,7 +2477,9 @@ private void mineNotificationsGUI(InventoryClickEvent e, Player p, String[] part typeNotification = "within"; // Execute command - Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " 0"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines set notification " + mineName + " " + typeNotification + " 0" )); // Cancel the event and close the inventory e.setCancelled(true); @@ -2471,7 +2505,9 @@ private void mineNotificationsGUI(InventoryClickEvent e, Player p, String[] part typeNotification = "disabled"; // Execute the command - Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " 0"); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines set notification " + mineName + " " + typeNotification + " 0" )); // Cancel the event and close the inventory e.setCancelled(true); @@ -2512,7 +2548,9 @@ private void radiusGUI(InventoryClickEvent e, Player p, String[] parts) { if (e.isLeftClick()){ // Execute the command - Bukkit.dispatchCommand(p,"mines set notification " + part2 + " " + typeNotification + " " + part3); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( + "mines set notification " + part2 + " " + typeNotification + " " + part3 )); // Cancel the event e.setCancelled(true); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIMenuTools.java index 195fb4b9b..c47c52a46 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIMenuTools.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotGUIMenuTools.java @@ -11,6 +11,7 @@ import com.cryptomorin.xseries.XMaterial; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -356,7 +357,8 @@ public boolean processGUIPage( Player p, String title, InventoryClickEvent e ) { if ( command != null ) { isPageAction = true; - Bukkit.dispatchCommand(p, command); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( command )); } } @@ -390,7 +392,8 @@ else if ( currentItem != null && currentItem.hasItemMeta() ) { if ( isMenuToolsPage && command != null ) { isPageAction = true; - Bukkit.dispatchCommand(p, command); + Bukkit.dispatchCommand(p, + Prison.get().getCommandHandler().findRegisteredCommand( command )); } } 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 33437fced..951149bb1 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 @@ -100,7 +100,10 @@ public void open() { // Create GUI but use the gui title as defined within the ConfigGui.yml file: PrisonGUI gui = new PrisonGUI(p, guiPageData.getDimension(), guiConfig.getString("Options.Titles.PlayerMinesGUI")); + + String guiItemNameDefault = guiConfig.getString( "Options.Mines.GuiItemNameDefault" ); + // Load the generic mine LORE that would be displayed first: List configCustomLore = guiConfig.getStringList("EditableLore.Mines"); @@ -122,6 +125,9 @@ public void open() { for (Mine m : minesDisplay) { // for (Mine m : mines.getSortedList()) { + String guiItemName = guiConfig.getString( "Options.Mines.GuiItemNames." + m.getName() ); + + // Init the lore array with default values for ladders ButtonLore minesLore = new ButtonLore(); @@ -140,8 +146,13 @@ public void open() { // Material material; - // Get Mine Name. - String mineName = m.getName(); + // Get Mine Name. First use 'guiItemName' if not null, then try to use 'guiItemNameDefault' + // if not null, and then use the mine's tag, or if that's null, then use the name: + String mineName = + guiItemName != null ? guiItemName : + guiItemNameDefault != null ? guiItemNameDefault : + m.getTag() != null ? m.getTag() : + m.getName(); // // Add mineName lore for TP. // minesLore.addLineLoreAction( "&3" + mineName ); @@ -261,7 +272,8 @@ public void open() { } - Button itemMine = new Button(null, xMat, minesLore, "&3" + mineTag); + Button itemMine = new Button(null, xMat, minesLore, mineName ); +// Button itemMine = new Button(null, xMat, minesLore, "&3" + mineTag); String mineTeleportCommand = Output.stringFormat( @@ -269,7 +281,7 @@ public void open() { m.getName(), p.getName() ); - // Before adding the button, add an NBT tag for the command and rank name: + // Before adding the button, add an NBT tag for the command and mine name: // PrisonNBTUtil nbtUtil = new PrisonNBTUtil(); // NBTItem nbtItem = nbtUtil == null ? null : nbtUtil.getNBT( itemMine.getButtonItem()); PrisonNBTUtil.setNBTBoolean( itemMine.getButtonItem(), SpigotGUIMenuTools.GUI_MENU_TOOLS_NBT_ENABLED, true); 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 4b1cccdb2..7e489f599 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 @@ -157,6 +157,11 @@ public void open() { PrisonGUI gui = new PrisonGUI(getPlayer(), guiPageData.getDimension(), guiConfig.getString("Options.Titles.PlayerRanksGUI")); + + + String guiItemNameDefault = guiConfig.getString( "Options.Ranks.GuiItemNameDefault" ); + + // Not sure how you want to represent this: XMaterial materialHas = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_gotten_rank")); XMaterial materialHasNot = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_not_gotten_rank")); @@ -184,9 +189,34 @@ public void open() { for ( Rank rank : ranksDisplay ) { - // hasAccess uses access by rank, and access by perm: - boolean playerHasThisRank = getRankPlayer() != null && getRankPlayer().hasAccessToRank( rank ); - + + String guiItemName = guiConfig.getString( "Options.Ranks.GuiItemNames." + rank.getName() ); + + // Get Rank Name. First use 'guiItemName' if not null, then try to use 'guiItemNameDefault' + // if not null, and then use the rank's tag, or if that's null, then use the name: + String rankName = + guiItemName != null ? guiItemName : + guiItemNameDefault != null ? guiItemNameDefault : + rank.getTag() != null ? rank.getTag() : + rank.getName(); + + + // hasAccess uses access by rank, and access by perm: + boolean playerHasThisRank = getRankPlayer() != null && getRankPlayer().hasAccessToRank( rank ); + + + // The valid names to use for Options.Ranks.MaterialType. must be + // based upon the XMaterial enumeration name, or supported past names. + String materialTypeStr = guiConfig.getString("Options.Ranks.MaterialType." + rank.getName()); + XMaterial materialType = + materialTypeStr == null ? null : + XMaterial.valueOf( materialTypeStr.toUpperCase() ); + + materialType = + !playerHasThisRank ? materialHasNot : + materialType != null ? materialType : + materialHas; + String rankLoreKey = "EditableLore.Rank." + ladderName + "." + rank.getName(); List rankLore = new ArrayList<>( configCustomLore ); List rankLore2 = guiConfig.getStringList( rankLoreKey ); @@ -215,7 +245,7 @@ public void open() { } for ( String stringValue : rankLore ) { - + String currency = (rank.getCurrency() == null || "default".equalsIgnoreCase( rank.getCurrency()) || rank.getCurrency().trim().length() == 0 ? @@ -246,9 +276,10 @@ public void open() { } Button itemRank = new Button(null, - playerHasThisRank ? materialHas : materialHasNot, + materialType, +// playerHasThisRank ? materialHas : materialHasNot, showNumber ? amount : 1, ranksLore, - rank.getTag() ); + rankName ); amount++; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java index 840eab86b..14649eeb5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java @@ -23,6 +23,7 @@ import java.util.List; import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.inventory.PlayerInventory; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; @@ -31,20 +32,161 @@ /** * Created by DMP9 on 04/02/2017. */ -public class SpigotPlayerInventory extends SpigotInventory implements PlayerInventory { +public class SpigotPlayerInventory + extends SpigotInventory + implements PlayerInventory { public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { super(wrapper); } - @Override public ItemStack[] getArmorContents() { + /** + *

This function gets all of the player's contents from the getContents(), + * getExtraContents(), and getArmorContents(). + *

+ * + * @return + */ + public List getAllContents() { + List results = new ArrayList<>(); + + for ( ItemStack iStack : getContents() ) { + if ( iStack != null ) { + results.add(iStack); + } + } + + try { + for ( ItemStack iStack : getExtraContents() ) { + if ( iStack != null ) { + results.add(iStack); + } + } + } catch (NoSuchMethodError e) { + // Ignore on older versions of spigot... Spigot 1.8.8 does not have this function. + } + + // then remove the armor ItemStacks: + for ( ItemStack iStack : getArmorContents() ) { + if ( iStack != null ) { + results.remove(iStack); + } + } + + return results; + } + + @Override + public void removeItem( ItemStack... iStack ) { + if ( iStack != null ) { + + // Remove all items... + super.removeItem(iStack); + + // But since this is a player's inventory, try to remove them from the players slots + for (ItemStack itemStack : iStack) { + PrisonBlock pBlock = itemStack.getMaterial(); + + if ( isPrisonBlockEqual( pBlock, getBoots() ) ) { + setBoots( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + if ( isPrisonBlockEqual( pBlock, getChestplate() ) ) { + setChestplate( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + if ( isPrisonBlockEqual( pBlock, getHelmet() ) ) { + setHelmet( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + if ( isPrisonBlockEqual( pBlock, getLeggings() ) ) { + setLeggings( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + + try { + + if ( isPrisonBlockEqual( pBlock, getItemInLeftHand() ) ) { + setItemInLeftHand( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + } + catch ( Exception e ) { + // java 1.8 may not be able to handle this + } + try { + + if ( isPrisonBlockEqual( pBlock, getItemInRightHand() ) ) { + setItemInRightHand( new SpigotItemStack( 0, PrisonBlock.AIR ) ); + } + } + catch ( Exception e ) { + // java 1.8 may not be able to handle this + } + + } + } + } + + + private boolean isPrisonBlockEqual( PrisonBlock pBlock, ItemStack iStack ) { + boolean results = false; + + if ( pBlock != null && iStack != null ) { + results = pBlock.equals( iStack.getMaterial() ); + } + + return results; + } + + @Override + public ItemStack[] getContents() { + List items = new ArrayList<>(); + Arrays.asList(((org.bukkit.inventory.PlayerInventory) getWrapper()).getContents()) + .forEach(x -> items.add(SpigotUtil.bukkitItemStackToPrison(x))); + return (ItemStack[]) items.toArray(); + } + + @Override + public void setContents( ItemStack[] items ) { + List stacks = new ArrayList<>(); + Arrays.asList(items).forEach(x -> stacks.add(SpigotUtil.prisonItemStackToBukkit(x))); + ((org.bukkit.inventory.PlayerInventory) getWrapper()) + .setContents((org.bukkit.inventory.ItemStack[]) stacks.toArray()); + } + + @Override + public ItemStack[] getExtraContents() { + try { + List items = new ArrayList<>(); + Arrays.asList(((org.bukkit.inventory.PlayerInventory) getWrapper()).getExtraContents()) + .forEach(x -> items.add(SpigotUtil.bukkitItemStackToPrison(x))); + return (ItemStack[]) items.toArray(); + } + catch ( Exception e ) { + return null; + } + } + @Override + public void setExtraContents( ItemStack[] items ) { + try { + List stacks = new ArrayList<>(); + Arrays.asList(items).forEach(x -> stacks.add(SpigotUtil.prisonItemStackToBukkit(x))); + ((org.bukkit.inventory.PlayerInventory) getWrapper()) + .setExtraContents((org.bukkit.inventory.ItemStack[]) stacks.toArray()); + } + catch ( Exception e ) { + // extraContents does not exist in spigot 1.8 + } + } + + + + @Override + public ItemStack[] getArmorContents() { List items = new ArrayList<>(); Arrays.asList(((org.bukkit.inventory.PlayerInventory) getWrapper()).getArmorContents()) .forEach(x -> items.add(SpigotUtil.bukkitItemStackToPrison(x))); return (ItemStack[]) items.toArray(); } - @Override public void setArmorContents(ItemStack[] items) { + @Override + public void setArmorContents(ItemStack[] items) { List stacks = new ArrayList<>(); Arrays.asList(items).forEach(x -> stacks.add(SpigotUtil.prisonItemStackToBukkit(x))); ((org.bukkit.inventory.PlayerInventory) getWrapper()) @@ -119,7 +261,8 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { } } - @Override public ItemStack getItemInRightHand() { + @Override + public ItemStack getItemInRightHand() { return SpigotUtil.bukkitItemStackToPrison( @@ -127,7 +270,8 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { ((org.bukkit.inventory.PlayerInventory) getWrapper()) )); } - @Override public void setItemInRightHand(ItemStack stack) { + @Override + public void setItemInRightHand(ItemStack stack) { if ( stack instanceof SpigotItemStack ) { @@ -135,5 +279,5 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { .setItemStackInMainHand( this, ((SpigotItemStack) stack) ); } } - + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/nbt/PrisonNBTUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/nbt/PrisonNBTUtil.java index c35f26d5d..415409308 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/nbt/PrisonNBTUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/nbt/PrisonNBTUtil.java @@ -1,9 +1,12 @@ package tech.mcprison.prison.spigot.nbt; +import java.util.function.Function; + import org.bukkit.inventory.ItemStack; import de.tr7zw.changeme.nbtapi.NBT; import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT; +import de.tr7zw.changeme.nbtapi.iface.ReadableItemNBT; import tech.mcprison.prison.output.Output; /** @@ -40,7 +43,10 @@ public static boolean hasNBTString( ItemStack bukkitStack, String key ) { public static String getNBTString( ItemStack bukkitStack, String key ) { String results = null; - results = NBT.get(bukkitStack, nbt -> nbt.getString(key)); + Function gsFnc = nbt -> nbt.getString(key); + + results = NBT.get(bukkitStack, gsFnc ); +// results = NBT.get(bukkitStack, nbt -> nbt.getString(key)); return results; } @@ -59,7 +65,10 @@ public static void setNBTString( ItemStack bukkitStack, String key, String value public static boolean getNBTBoolean( ItemStack bukkitStack, String key ) { boolean results = false; - results = NBT.get(bukkitStack, nbt -> nbt.getBoolean(key)); + Function gbFnc = nbt -> nbt.getBoolean(key); + + results = NBT.get(bukkitStack, gbFnc ); +// results = NBT.get(bukkitStack, nbt -> nbt.getBoolean(key)); return results; } 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 d95853d7b..72cb87a07 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 @@ -25,6 +25,7 @@ import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.game.SpigotPlayer; public class SpigotPlaceholders implements Placeholders { @@ -70,6 +71,38 @@ private void initializePlaceholderManagers() { } } + private boolean ignorePlayerInDisabledWorlds( SpigotPlayer sPlayer ) { + boolean results = false; + + String worldName = + sPlayer == null || + sPlayer.getLocation() == null || + sPlayer.getLocation().getWorld() == null ? + null : + sPlayer.getLocation().getWorld().getName(); + + if ( worldName != null && sPlayer.isOnline() ) { + + boolean disable = Prison.get().getPlatform().getConfigBooleanFalse( + "prisonCommandHandler.disable-player-placeholders-in-excluded-worlds" ); + if ( disable ) { + List excludedWorlds = Prison.get().getPlatform() + .getConfigStringArray( "prisonCommandHandler.exclude-worlds" ); + for (String world : excludedWorlds) { + if ( world.trim().equalsIgnoreCase( worldName ) ) { + results = true; + break; + } + } + } + } + + if ( results ) { + PlaceholdersStats.getInstance().incrementInvalidWorldCount(); + } + + return results; + } @Override public Map getPlaceholderDetailCounts() { @@ -170,7 +203,7 @@ public int getPlaceholderRegistrationCount() { /** *

Provides placeholder translation for any placeholder identifier - * that is provided. This not the full text with one or more placeholders, + * that is provided. This not for full text with one or more placeholders, * but it is strictly just the placeholder. *

* @@ -425,6 +458,13 @@ private String replaceAllPlaceholders(UUID playerUuid, String playerName, String String replacementText = processPlaceholderIdentifier(identifier); if ( identifier.isFoundAMatch() ) { + + if ( identifier.getPlayer() != null && + identifier.getPlayer() instanceof SpigotPlayer && + ignorePlayerInDisabledWorlds( (SpigotPlayer) identifier.getPlayer() )) { + replacementText = ""; + } + results = results.replace( placeholderText, replacementText ); } @@ -481,6 +521,10 @@ public List placeholderSearch( UUID playerUuid, String playerName, Strin String value = processPlaceholderHavePlaceholderKey( identifier ); + if ( ignorePlayerInDisabledWorlds( (SpigotPlayer) identifier.getPlayer() )) { + value = ""; + } + // Note: STATSMINES will not work here since the sequence is not being addressed. // if ( mm != null && (placeHolderKey.getPlaceholder().hasFlag( PlaceholderFlags.MINES ) || diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllData.java new file mode 100644 index 000000000..9d7555fba --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllData.java @@ -0,0 +1,159 @@ +package tech.mcprison.prison.spigot.sellall; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.game.SpigotPlayer; + +/** + *

This is a simple class that contains the times that have been sold + * and the amount that they were sold for. + *

+ * + * @author Blue + * + */ +public class SellAllData { + + private PrisonBlock prisonBlock; + private int quantity; + private double transactionAmount; + private boolean itemsSold; + + public SellAllData( PrisonBlock pBlock, int quantity, double transactionAmount ) { + super(); + + this.itemsSold = false; + + this.prisonBlock = pBlock; + this.quantity = quantity; + this.transactionAmount = transactionAmount; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + DecimalFormat dFmt = new DecimalFormat( "#,##0.00" ); + sb.append( getPrisonBlock().getBlockName() ) + .append( ":" ) + .append( getQuantity() ) + .append( ":" ) + .append( dFmt.format(getTransactionAmount()) ); + + if ( isItemsSold() ) { + sb.append( ":SOLD" ); + } + + return sb.toString(); + } + + + public static void debugItemsSold( List soldItems, SpigotPlayer sPlayer, double multiplier ) { + if ( Output.get().isDebug() ) { + String report = SellAllData.itemsSoldReport( soldItems, sPlayer, multiplier ); + Output.get().logDebug( report, (sPlayer != null ? sPlayer.getName() : null) ); + } + } + + public static String itemsSoldReport( List soldItems, SpigotPlayer sPlayer, double multiplier ) { + StringBuilder sb = new StringBuilder(); + StringBuilder sbItems = new StringBuilder(); + + double totalAmount = 0; + int itemCount = 0; + int stacks = soldItems.size(); + + // Add same blocks together: + soldItems = compressSoldItems( soldItems ); + + for (SellAllData soldItem : soldItems) { + if ( soldItem != null ) { + + totalAmount += soldItem.getTransactionAmount(); + itemCount += soldItem.getQuantity(); + + if ( sbItems.length() > 0 ) { + + sbItems.append( ", " ); + } + sbItems.append( soldItem.toString() ); + } + } + + DecimalFormat dFmt = new DecimalFormat( "#,##0.00" ); + DecimalFormat iFmt = new DecimalFormat( "#,##0" ); + + sb.append( "Transaction log: " ) + .append( sPlayer.getName() ) + .append( " multiplier: " ) + .append( dFmt.format(multiplier) ) + .append( " ItemStacks: " ) + .append( stacks ) + .append( " ItemCount: " ) + .append( iFmt.format(itemCount) ) + .append( " TotalAmount: " ) + .append( dFmt.format( totalAmount )) + .append( " [" ) + .append( sbItems ) + .append("]"); + + return sb.toString(); + } + + private static List compressSoldItems(List soldItems) { + List results = new ArrayList<>(); + + for (SellAllData sItem : soldItems) { + boolean found = false; + + for (SellAllData result : results) { + if ( sItem.getPrisonBlock().equals(result.getPrisonBlock() ) ) { + found = true; + + // found a match... add to the result item: + result.setQuantity( result.getQuantity() + sItem.getQuantity() ); + result.setTransactionAmount( result.getTransactionAmount() + sItem.getTransactionAmount() ); + break; + } + } + + if ( !found ) { + results.add(sItem); + } + } + + return results; + } + + public PrisonBlock getPrisonBlock() { + return prisonBlock; + } + public void setPrisonBlock(PrisonBlock prisonBlock) { + this.prisonBlock = prisonBlock; + } + + public int getQuantity() { + return quantity; + } + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public double getTransactionAmount() { + return transactionAmount; + } + public void setTransactionAmount(double transactionAmount) { + this.transactionAmount = transactionAmount; + } + + public boolean isItemsSold() { + return itemsSold; + } + public void setItemsSold(boolean itemsSold) { + this.itemsSold = itemsSold; + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index ec41604a3..1acf5a8eb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -9,27 +9,22 @@ import java.util.Optional; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.Sound; 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 org.bukkit.inventory.PlayerInventory; import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; -import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; 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.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.PlayerRank; @@ -37,16 +32,12 @@ import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.sellall.messages.SpigotVariousGuiMessages; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; -import tech.mcprison.prison.spigot.compat.Compatibility; -import tech.mcprison.prison.spigot.compat.SpigotCompatibility; //import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotCommandSender; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminGUI; import tech.mcprison.prison.spigot.gui.sellall.SellAllPlayerGUI; -import tech.mcprison.prison.spigot.integrations.IntegrationMinepacksPlugin; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.util.Text; @@ -58,23 +49,25 @@ public class SellAllUtil private static SellAllUtil instance; - private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); +// private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); - private final ItemStack lapisLazuli = compat.getLapisItemStack(); +// private final ItemStack lapisLazuli = compat.getLapisItemStack(); public Configuration sellAllConfig; - private HashMap sellAllBlocks; + private HashMap sellAllItems; +// private HashMap sellAllBlocks; + private HashMap sellAllPrestigeMultipliers; private HashMap autoSellEarningsNotificationWaiting = new HashMap<>(); private ArrayList sellAllItemTriggers; private ArrayList activePlayerDelay = new ArrayList<>(); - private List sellAllDisabledWorlds; +// private List sellAllDisabledWorlds; // private MessagesConfig messages; private double defaultMultiplier; private int defaultSellAllDelay; private int defaultAutoSellEarningNotificationDelay; - private Sound sellAllSoundSuccess; + public Sound sellAllSoundSuccess; private Sound sellAllSoundFail; public String sellAllSignTag; public String sellAllCurrency; @@ -107,6 +100,8 @@ public class SellAllUtil public boolean isSellAllSignNotifyEnabled; public boolean isSellAllSignPermissionToUseEnabled; public boolean isSellAllNotificationEnabled; + public boolean isSellAllNotificationByActionBar; + public boolean isSellAllSoundEnabled; public boolean isSellAllBackpackItemsEnabled; public boolean isSellAllMinesBackpacksPluginEnabled; @@ -129,16 +124,107 @@ public static SellAllUtil get() { } return instance; } - + /** - * Return boolean value from String. - * - * @return boolean. + * Init options that will be cached. * */ - private static boolean getBoolean(String string) { - return string != null && string.equalsIgnoreCase("true"); + private void initCachedData() { + sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); +// messages = SpigotPrison.getInstance().getMessagesConfig(); + permissionSellAllSell = sellAllConfig.getString("Options.Sell_Permission"); + permissionBypassSign = sellAllConfig.getString("Options.SellAll_By_Sign_Bypass_Permission"); + permissionUseSign = sellAllConfig.getString("Options.SellAll_Sign_Use_Permission"); + permissionGUI = sellAllConfig.getString("Options.GUI_Permission"); + permissionPlayerGUI = sellAllConfig.getString("Options.Player_GUI_Permission"); + permissionPrefixBlocks = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); + permissionAutoSellPerUserToggleable = sellAllConfig.getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission"); + permissionItemTrigger = sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Permission"); + sellAllCurrency = sellAllConfig.getString("Options.SellAll_Currency"); + sellAllSoundSuccess = XSound.matchXSound("Options.Sell_Sound_Success_Name").orElse(XSound.ENTITY_PLAYER_LEVELUP).parseSound(); + sellAllSoundFail = XSound.matchXSound("Options.Sell_Sound_Fail_Name").orElse(XSound.BLOCK_ANVIL_PLACE).parseSound(); + sellAllSignTag = Text.translateAmpColorCodes(sellAllConfig.getString("Options.SellAll_Sign_Visible_Tag") ); +// sellAllBlocks = initSellAllBlocks(); + sellAllItems = initSellAllItems(); + + sellAllPrestigeMultipliers = initPrestigeMultipliers(); + sellAllItemTriggers = initSellAllItemTrigger(); +// sellAllDisabledWorlds = initSellAllDisabledWorlds(); + defaultMultiplier = Double.parseDouble(sellAllConfig.getString("Options.Multiplier_Default")); + defaultSellAllDelay = Integer.parseInt(sellAllConfig.getString("Options.Sell_Delay_Seconds")); + defaultAutoSellEarningNotificationDelay = Integer.parseInt(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Delay_Seconds")); + isPerBlockPermissionEnabled = getBooleanValue("Options.Sell_Per_Block_Permission_Enabled"); + isAutoSellEnabled = getBooleanValue("Options.Full_Inv_AutoSell"); + isAutoSellNotificationEnabled = getBooleanValue("Options.Full_Inv_AutoSell_Notification"); + isAutoSellEarningNotificationDelayEnabled = getBooleanValue("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled"); + isAutoSellPerUserToggleable = getBooleanValue("Options.Full_Inv_AutoSell_perUserToggleable"); + isAutoSellPerUserToggleablePermEnabled = getBooleanValue("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm"); + isSellAllNotificationEnabled = getBooleanValue("Options.Sell_Notify_Enabled"); + isSellAllNotificationByActionBar = getBooleanValue("Options.Sell_Notify_by_ActionBar"); + + isSellAllSoundEnabled = getBooleanValue("Options.Sell_Sound_Enabled"); + isSellAllBackpackItemsEnabled = getBooleanValue("Options.Sell_Prison_BackPack_Items"); + isSellAllMinesBackpacksPluginEnabled = getBooleanValue("Options.Sell_MinesBackPacks_Plugin_Backpack"); + isSellAllDelayEnabled = getBooleanValue("Options.Sell_Delay_Enabled"); + + isSellAllSellPermissionEnabled = getBooleanValue("Options.Sell_Permission_Enabled"); + isSellAllItemTriggerEnabled = getBooleanValue("Options.ShiftAndRightClickSellAll.Enabled"); + isSellAllItemTriggerPermissionEnabled = getBooleanValue("Options.ShiftAndRightClickSellAll.PermissionEnabled"); + isSellAllGUIEnabled = getBooleanValue("Options.GUI_Enabled"); + isSellAllPlayerGUIEnabled = getBooleanValue("Options.Player_GUI_Enabled"); + isSellAllGUIPermissionEnabled = getBooleanValue("Options.GUI_Permission_Enabled"); + isSellAllPlayerGUIPermissionEnabled = getBooleanValue("Options.Player_GUI_Permission_Enabled"); + isSellAllMultiplierEnabled = getBooleanValue("Options.Multiplier_Enabled"); + isSellAllPermissionMultiplierOnlyHigherEnabled = getBooleanValue("Options.Multiplier_Permission_Only_Higher"); + isSellAllSignEnabled = getBooleanValue("Options.SellAll_Sign_Enabled"); + isSellAllSignNotifyEnabled = getBooleanValue("Options.SellAll_Sign_Notify"); + isSellAllSignPermissionToUseEnabled = getBooleanValue("Options.SellAll_Sign_Use_Permission_Enabled"); + isSellAllBySignOnlyEnabled = getBooleanValue("Options.SellAll_By_Sign_Only"); + isSellAllHandEnabled = getBooleanValue("Options.SellAll_Hand_Enabled"); + + isSellAllIgnoreCustomNames = getBooleanValue("Options.SellAll_ignoreCustomNames", false); + } + + private boolean getBooleanValue( String configName ) { + return getBooleanValue(configName, false); + } + private boolean getBooleanValue( String configName, Boolean defaultValue ) { + boolean results = (defaultValue == null ? false : defaultValue.booleanValue() ); + + if ( configName != null ) { + if ( sellAllConfig.isString(configName) ) { + String boolVal = sellAllConfig.getString(configName); + if ( boolVal != null ) { + // Boolean.parseBoolean() also supports yes and no so don't pretest for true/false. + try { + results = Boolean.parseBoolean(boolVal); + } catch (Exception e) { + // Not a boolean value, so ignore and let the "defaut" value stand + } + } + else { + // ignore since it's not a boolean value and let the "default" value stand + } + } + else if ( sellAllConfig.isBoolean(configName) ) { + results = sellAllConfig.getBoolean(configName, results); + } + else { + // Ignore since the config is not boolean or a String that "could" be a boolean + } + } + + return results; } +// /** +// * Return boolean value from String. +// * +// * @return boolean. +// * */ +// private static boolean getBoolean(String string) { +// return string != null && string.equalsIgnoreCase("true"); +// } + /** * Get an ArrayList of SellAllItemTriggers as XMaterials. * These items will trigger sellall when a player hold them and then do shift+right click in the air. @@ -172,60 +258,68 @@ public ArrayList getItemTriggerXMaterials(){ // return materials; // } - /** - * Get SellAll XMaterial or Lapis (As Lapis is weird) from an ItemStack. - * - * @param itemStack - ItemStack. - * - * @return XMaterial. - * */ - private XMaterial getXMaterialOrLapis(ItemStack itemStack) { - XMaterial results = null; - - String altName = null; - - if ( itemStack.hasItemMeta() && itemStack.getItemMeta().hasDisplayName() ) { - altName = itemStack.getItemMeta().getDisplayName(); - } - - if ( altName == null || isSellAllIgnoreCustomNames ) { - XMaterial xMat = null; - - if (itemStack.isSimilar(lapisLazuli)) { - xMat = XMaterial.LAPIS_LAZULI; - } - else { - - try - { - xMat = XMaterial.matchXMaterial(itemStack); - } - catch ( Exception e ) - { - // ignore... it is not normal matertial so it cannot be sold - } - } - if ( xMat != null ) { - - // When converted over to be based upon a String name, instead of XMaterial, - // the altName will take priority over the XMaterial name. - results = xMat; - } - } - - return results; - } +// /** +// * Get SellAll XMaterial or Lapis (As Lapis is weird) from an ItemStack. +// * +// * @param itemStack - ItemStack. +// * +// * @return XMaterial. +// * */ +// private XMaterial getXMaterialOrLapis(ItemStack itemStack) { +// XMaterial results = null; +// +// String altName = null; +// +// if ( itemStack.hasItemMeta() && itemStack.getItemMeta().hasDisplayName() ) { +// altName = itemStack.getItemMeta().getDisplayName(); +// } +// +// if ( altName == null || isSellAllIgnoreCustomNames ) { +// XMaterial xMat = null; +// +// if (itemStack.isSimilar(lapisLazuli)) { +// xMat = XMaterial.LAPIS_LAZULI; +// } +// else { +// +// try +// { +// xMat = XMaterial.matchXMaterial(itemStack); +// } +// catch ( Exception e ) +// { +// // ignore... it is not normal matertial so it cannot be sold +// } +// } +// if ( xMat != null ) { +// +// // When converted over to be based upon a String name, instead of XMaterial, +// // the altName will take priority over the XMaterial name. +// results = xMat; +// } +// } +// +// return results; +// } - /** - * Return SellAll Blocks HashMap cached values. - * - * @return HashMap of XMaterial-Double. - * */ - public HashMap getSellAllBlocks() { - return sellAllBlocks; - } +// /** +// * Return SellAll Blocks HashMap cached values. +// * +// * @return HashMap of XMaterial-Double. +// * */ +// public HashMap getSellAllBlocks() { +// return sellAllBlocks; +// } /** + * + * @return HashMap + */ + public HashMap getSellAllItems() { + return sellAllItems; + } + + /** * Return SellAll Prestige Multiplier HashMap read before from config on init. * * HashMap details: @@ -238,64 +332,64 @@ public HashMap getPrestigeMultipliers() { return sellAllPrestigeMultipliers; } - /** - * Get HashMap of XMaterials and amounts from an Inventory. - * - * @param inv - Inventory. - * - * @return HashMap of XMaterials and Integers. - * */ - public HashMap getXMaterialsHashMapFromInventory(Inventory inv){ - - HashMap xMaterialIntegerHashMap = new HashMap<>(); - for (ItemStack itemStack : inv.getContents()){ - if (itemStack != null){ - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - if ( xMaterial != null ) { - - if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0){ - xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); - } - else { - xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); - } - } - } - } - - return xMaterialIntegerHashMap; - } - +// /** +// * Get HashMap of XMaterials and amounts from an Inventory. +// * +// * @param inv - Inventory. +// * +// * @return HashMap of XMaterials and Integers. +// * */ +// private HashMap getXMaterialsHashMapFromInventory(Inventory inv){ +// +// HashMap xMaterialIntegerHashMap = new HashMap<>(); +// for (ItemStack itemStack : inv.getContents()){ +// if (itemStack != null){ +// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +// if ( xMaterial != null ) { +// +// if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0){ +// xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); +// } +// else { +// xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); +// } +// } +// } +// } +// +// return xMaterialIntegerHashMap; +// } - /** - * get HashMap of XMaterials and Amounts from an ArrayList of ItemStacks. - * - * @param itemStacks - ArrayList of ItemStacks. - * - * @return HashMap of XMaterials and Integers. - * */ - public HashMap getXMaterialsHashMapFromArrayList(ArrayList itemStacks){ - - HashMap xMaterialIntegerHashMap = new HashMap<>(); - for (ItemStack itemStack : itemStacks){ - if (itemStack != null){ - try { - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - if ( xMaterial != null ) { - - if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0) { - xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); - } - else { - xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); - } - } - } catch (IllegalArgumentException ignored){} - } - } - return xMaterialIntegerHashMap; - } +// /** +// * get HashMap of XMaterials and Amounts from an ArrayList of ItemStacks. +// * +// * @param itemStacks - ArrayList of ItemStacks. +// * +// * @return HashMap of XMaterials and Integers. +// * */ +// private HashMap getXMaterialsHashMapFromArrayList(ArrayList itemStacks){ +// +// HashMap xMaterialIntegerHashMap = new HashMap<>(); +// for (ItemStack itemStack : itemStacks){ +// if (itemStack != null){ +// try { +// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +// if ( xMaterial != null ) { +// +// if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0) { +// xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); +// } +// else { +// xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); +// } +// } +// } catch (IllegalArgumentException ignored){} +// } +// } +// +// return xMaterialIntegerHashMap; +// } /** * Get SellAll Player Multiplier. @@ -389,259 +483,508 @@ public double getPlayerMultiplier(Player p){ return multiplier; } - /** - * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. - * NOTE: This WON'T remove blocks from the HashMap when sold, and won't edit Inventories of Players, - * but only return the amount of money that the Player would get if he sells now everything from the - * specified HashMap of XMaterials and Integers. - * - * Will also calculate the Multiplier of the Player. - * - * Get SellAll Sell value of HashMap values. - * NOTE: If there aren't blocks in the SellAll shop this will return 0. - * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. - * - * @param p - Player. - * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). - * - * @return double. - * */ - public double getSellMoney(Player p, HashMap xMaterialIntegerHashMap){ - StringBuilder sb = new StringBuilder(); - boolean debug = Output.get().isDebug(); +// /** +// * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. +// * NOTE: This WON'T remove blocks from the HashMap when sold, and won't edit Inventories of Players, +// * but only return the amount of money that the Player would get if he sells now everything from the +// * specified HashMap of XMaterials and Integers. +// * +// * Will also calculate the Multiplier of the Player. +// * +// * Get SellAll Sell value of HashMap values. +// * NOTE: If there aren't blocks in the SellAll shop this will return 0. +// * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. +// * +// * @param p - Player. +// * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). +// * +// * @return double. +// * */ +// private double getSellMoney(Player p, HashMap xMaterialIntegerHashMap){ +// StringBuilder sb = new StringBuilder(); +// boolean debug = Output.get().isDebug(); +// +// if (sellAllItems.isEmpty()){ +// return 0; +// } +// +// double multiplier = getPlayerMultiplier(p); +// +// +// double earned = 0; +// for (HashMap.Entry xMatEntry : xMaterialIntegerHashMap.entrySet()){ +// +// PrisonBlock pBlockKey = Prison.get().getPlatform().getPrisonBlock( xMatEntry.getKey().name() ); +// +// String key = pBlockKey.getBlockName(); +// +// if (sellAllItems.containsKey( key )){ +// // This is stupid but right now I'm too confused, sorry. +// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + key )){ +// // Nothing will change. +// } +// else { +// PrisonBlock pBlock = sellAllItems.get(key); +// +//// XMaterial xMat = xMatEntry.getKey(); +// int qty = xMatEntry.getValue(); +// double value = pBlock.getSalePrice(); +// +// if ( debug ) { +// +// if ( sb.length() > 0 ) { +// sb.append(", "); +// } +// sb.append( key.toLowerCase() ).append(":") +// .append( qty ).append("@").append(value); +// } +// +// earned += qty * value; +// } +// } +// } +// +// double total = earned * multiplier; +// +// if ( debug ) { +// DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.00" ); +// sb.append( " earned: " ).append( dFmt.format(earned) ) +// .append( " mult: " ).append( dFmt.format(multiplier) ) +// .append( " total: " ).append( dFmt.format(total) ); +// String message = String.format( +// "Sellall.getSellMoney: %s %s", +// p.getName(), sb.toString() ); +// Output.get().logInfo(message); +// } +// +// return total; +// } - if (sellAllBlocks.isEmpty()){ - return 0; - } +// /** +// * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. +// * NOTE: This WON'T remove blocks from the ArrayList when sold, and won't edit Inventories of Players, +// * but only return the amount of money that the Player would get if he sells now everything from the +// * specified ArrayList of ItemStacks. +// * +// * Will also calculate the Multiplier of the Player. +// * +// * Get SellAll Sell value of ArrayList of itemstack. +// * NOTE: If there aren't blocks in the SellAll shop this will return 0. +// * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. +// * +// * @param p - Player. +// * @param itemStacks - ArrayList of ItemStacks (Blocks of origin). +// * +// * @return double. +// * */ +// private double getSellMoney(Player p, ArrayList itemStacks){ +// HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); +// return getSellMoney(p, xMaterialIntegerHashMap); +// } + + + public double getPlayerInventoryValue( SpigotPlayer sPlayer ) { + double value = 0; + + double multiplier = getPlayerMultiplier(sPlayer.getWrapper()); - double multiplier = getPlayerMultiplier(p); - - - double earned = 0; - for (HashMap.Entry xMatEntry : xMaterialIntegerHashMap.entrySet()){ - if (sellAllBlocks.containsKey(xMatEntry.getKey())){ - // This is stupid but right now I'm too confused, sorry. - if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMatEntry.getKey().name())){ - // Nothing will change. - } - else { - XMaterial xMat = xMatEntry.getKey(); - int qty = xMatEntry.getValue(); - double value = sellAllBlocks.get(xMat); - - if ( debug ) { - - if ( sb.length() > 0 ) { - sb.append(", "); - } - sb.append( xMat.name().toLowerCase() ).append(":") - .append( qty ).append("@").append(value); - } - - earned += qty * value; - } - } - } + SpigotPlayerInventory spInventory = sPlayer.getSpigotPlayerInventory(); - double total = earned * multiplier; - - if ( debug ) { - DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.00" ); - sb.append( " earned: " ).append( dFmt.format(earned) ) - .append( " mult: " ).append( dFmt.format(multiplier) ) - .append( " total: " ).append( dFmt.format(total) ); - String message = String.format( - "Sellall.getSellMoney: %s %s", - p.getName(), sb.toString() ); - Output.get().logInfo(message); - } - - return total; + List soldItems = valueOfInventoryItems( spInventory, multiplier ); + for (SellAllData soldItem : soldItems) { + value += soldItem.getTransactionAmount(); + } + + return value; } - - /** - * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. - * NOTE: This WON'T remove blocks from the ArrayList when sold, and won't edit Inventories of Players, - * but only return the amount of money that the Player would get if he sells now everything from the - * specified ArrayList of ItemStacks. - * - * Will also calculate the Multiplier of the Player. - * - * Get SellAll Sell value of ArrayList of itemstack. - * NOTE: If there aren't blocks in the SellAll shop this will return 0. - * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. - * - * @param p - Player. - * @param itemStacks - ArrayList of ItemStacks (Blocks of origin). - * - * @return double. - * */ - public double getSellMoney(Player p, ArrayList itemStacks){ - HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); - return getSellMoney(p, xMaterialIntegerHashMap); + + public String getPlayerInventoryValueReport( SpigotPlayer sPlayer ) { + + double multiplier = getPlayerMultiplier(sPlayer.getWrapper()); + + SpigotPlayerInventory spInventory = sPlayer.getSpigotPlayerInventory(); + + List soldItems = valueOfInventoryItems( spInventory, multiplier ); + + String report = SellAllData.itemsSoldReport(soldItems, sPlayer, multiplier); + + return report; } - - /** - * Get SellAll Sell Money, calculated from all the enabled backpacks (from sellAll config and integrations) and - * main inventory. - * NOTE: This WON'T remove blocks from Inventories/Backpacks, but only return their value. - * - * Will also calculate the Multiplier of the Player. - * - * NOTE: If there aren't blocks in the SellAll shop this will return 0. - * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. - * - * @param p - Player. - * - * @return double. - * */ - public double getSellMoney(Player p){ - - if (sellAllBlocks.isEmpty()){ - return 0; - } - - return getSellMoney(p, getHashMapOfPlayerInventories(p)); + + public List getPlayerInventoryValueTransactions( SpigotPlayer sPlayer ) { + + double multiplier = getPlayerMultiplier(sPlayer.getWrapper()); + + SpigotPlayerInventory spInventory = sPlayer.getSpigotPlayerInventory(); + + List soldItems = valueOfInventoryItems( spInventory, multiplier ); + + return soldItems; } + + + public double getItemStackValue( SpigotPlayer player, SpigotItemStack itemStack ) { + + double multiplier = getPlayerMultiplier(player.getWrapper()); + + SellAllData sad = sellItemStack( itemStack, multiplier ); + + return sad == null ? 0 : sad.getTransactionAmount(); + } + + public String getItemStackValueReport( SpigotPlayer sPlayer, SpigotItemStack itemStack ) { + + double multiplier = getPlayerMultiplier(sPlayer.getWrapper()); + + List soldItems = new ArrayList<>(); + + SellAllData sad = sellItemStack( itemStack, multiplier ); + if ( sad != null ) { + + soldItems.add( sad ); + } + + String report = SellAllData.itemsSoldReport(soldItems, sPlayer, multiplier); + + return report; + } + + public List getItemStackValueTransactions( SpigotPlayer sPlayer, SpigotItemStack itemStack ) { + + double multiplier = getPlayerMultiplier(sPlayer.getWrapper()); + + List soldItems = new ArrayList<>(); + + SellAllData sad = sellItemStack( itemStack, multiplier ); + if ( sad != null ) { + + soldItems.add( sad ); + } + + return soldItems; + } + + /** + *

This sells the players inventory, and removes what is sold. + * This returns the transaction logs within the SellAllData obects. + *

+ * + * @param p + * @return + */ + public List sellPlayerItems(Player p) { + + double multiplier = getPlayerMultiplier(p); + + SpigotPlayer sPlayer = new SpigotPlayer( p ); + + SpigotPlayerInventory spInventory = sPlayer.getSpigotPlayerInventory(); + + return sellInventoryItems( spInventory, multiplier ); + } + /** - *

This sells a specific item stack. Actually it returns the value of an item stack, - * its up to the calling function to dispose of the contents if the result is non-zero. + *

This function sells the Item Stacks and returns a transaction log of items sold. + * This is an internal function. No messages are sent, most sellall options are bypassed, + * etc... Use at your own risk. + *

+ * + *

The parameter itemStacks will have the items sold removed. The sold items will + * be reflected in the returned transaction logs. *

+ * * @param p - * @param itemStack + * @param itemStacks * @return */ - public double getSellMoney( Player p, SpigotItemStack itemStack ) - { - double results = 0d; + public List sellPlayerItemStacks(Player p, + List itemStacks ) { - // Either ignore custom names, or if isSellAllIgnoreCustomNames is set, then allow them - // to be processed as they used to be processed. + double multiplier = getPlayerMultiplier(p); - // For now, do not sell custom blocks since this sellall is based upon - // XMaterial and custom blocks cannot be represented by XMaterial so - // it will sell it as the wrong material - if ( isSellAllIgnoreCustomNames || - itemStack.getMaterial().getBlockType() == null || - itemStack.getMaterial().getBlockType() == PrisonBlockType.minecraft ) { + List soldItems = new ArrayList<>(); + + if ( itemStacks != null ) { - HashMap xMaterialIntegerHashMap = new HashMap<>(); + List removable = new ArrayList<>(); - PrisonBlock pBlock = itemStack.getMaterial(); + // Go through all of the player's inventory and identify what can be sold. + // 1. if it can be sold, then create a SellAllData "receipt" + // 2. Add sad to the soldItems List + // 3. Add the ItemStack to the removable List to be removed later + for ( SpigotItemStack inv : itemStacks ) { + + SellAllData sad = sellItemStack( inv, multiplier ); + + if ( sad != null ) { + + sad.setItemsSold( true ); + + soldItems.add(sad); + + removable.add(inv); + } + } - XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial( pBlock ); + // We've identified all that could be sold, now remove them from the player's inventory + for (tech.mcprison.prison.internal.ItemStack itemStack : removable) { + itemStacks.remove( itemStack ); + } + } + + return soldItems; + } + + + private List sellInventoryItems( tech.mcprison.prison.internal.inventory.Inventory inventory, double multiplier ) { + List soldItems = new ArrayList<>(); + + if ( inventory != null ) { + + List removable = new ArrayList<>(); - if ( xMat != null ) { - xMaterialIntegerHashMap.put( xMat, itemStack.getAmount() ); + // Go through all of the player's inventory and identify what can be sold. + // 1. if it can be sold, then create a SellAllData "receipt" + // 2. Add sad to the soldItems List + // 3. Add the ItemStack to the removable List to be removed later + for ( tech.mcprison.prison.internal.ItemStack inv : inventory.getItems() ) { - results = getSellMoney( p, xMaterialIntegerHashMap ); + SellAllData sad = sellItemStack( (SpigotItemStack)inv, multiplier ); + + if ( sad != null ) { + + sad.setItemsSold( true ); + + soldItems.add(sad); + + removable.add(inv); + } + } + + // We've identified all that could be sold, now remove them from the player's inventory + for (tech.mcprison.prison.internal.ItemStack itemStack : removable) { + inventory.removeItem( itemStack ); } } + return soldItems; + } + + private List valueOfInventoryItems( + tech.mcprison.prison.internal.inventory.Inventory inventory, double multiplier ) { + List soldItems = new ArrayList<>(); + + if ( inventory != null ) { + + for ( tech.mcprison.prison.internal.ItemStack inv : inventory.getItems() ) { + + SellAllData sad = sellItemStack( (SpigotItemStack)inv, multiplier ); + + if ( sad != null ) { + soldItems.add(sad); + } + } + } - return results; - } - + return soldItems; + } /** - *

This gets the player's inventory, ignoring the armor slots.

+ *

This takes an SpigotItemStack and generates a SellAllData items with + * the transaction amount based upon how many items are in the itemStack, + * times the salePrice, times the player's multiplier. + * This function DOES NOT remove anything from any ItemStack, any Inventory, + * or any player's inventory. This function does not pay the player + * anything. This just generates the transaction. + *

* - * @param p + * @param iStack + * @param multiplier * @return */ - private List getPlayerInventory( Player p ) { + private SellAllData sellItemStack( SpigotItemStack iStack, double multiplier ) { + SellAllData soldItem = null; - return getPlayerInventory( p.getInventory() ); + if ( iStack != null ) { + + PrisonBlock pBlockInv = iStack.getMaterial(); + PrisonBlock pBlockSellAll = sellAllItems.get( pBlockInv.getBlockName().toLowerCase() ); + + if ( pBlockSellAll != null ) { + double amount = iStack.getAmount() * pBlockSellAll.getSalePrice() * multiplier; + soldItem = new SellAllData( pBlockSellAll, iStack.getAmount(), amount ); + + } + } -// List results = new ArrayList<>(); + return soldItem; + } + +// /** +// * Get SellAll Sell Money, calculated from all the enabled backpacks (from sellAll config and integrations) and +// * main inventory. +// * NOTE: This WON'T remove blocks from Inventories/Backpacks, but only return their value. +// * +// * Will also calculate the Multiplier of the Player. +// * +// * NOTE: If there aren't blocks in the SellAll shop this will return 0. +// * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. +// * +// * @param p - Player. +// * +// * @return double. +// * */ +// public double getSellMoney(Player p){ +// +// if (sellAllItems.isEmpty()){ +// return 0; +// } +// +// return getSellMoney(p, getHashMapOfPlayerInventories(p)); +// } + +// /** +// *

This sells a specific item stack. Actually it returns the value of an item stack, +// * its up to the calling function to dispose of the contents if the result is non-zero. +// *

+// * @param p +// * @param itemStack +// * @return +// */ +// private double getSellMoney( Player p, SpigotItemStack itemStack ) +// { +// double results = 0d; +// +// // Either ignore custom names, or if isSellAllIgnoreCustomNames is set, then allow them +// // to be processed as they used to be processed. +// +// // For now, do not sell custom blocks since this sellall is based upon +// // XMaterial and custom blocks cannot be represented by XMaterial so +// // it will sell it as the wrong material +// if ( isSellAllIgnoreCustomNames || +// itemStack.getMaterial().getBlockType() == null || +// itemStack.getMaterial().getBlockType() == PrisonBlockType.minecraft ) { +// +// HashMap xMaterialIntegerHashMap = new HashMap<>(); +// +// PrisonBlock pBlock = itemStack.getMaterial(); +// +// XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial( pBlock ); +// +// if ( xMat != null ) { +// xMaterialIntegerHashMap.put( xMat, itemStack.getAmount() ); +// +// results = getSellMoney( p, xMaterialIntegerHashMap ); +// } +// } +// +// +// return results; +// } + + +// /** +// *

This gets the player's inventory, ignoring the armor slots.

+// * +// * @param p +// * @return +// */ +// private List getPlayerInventory( Player p ) { +// +// return getPlayerInventory( p.getInventory() ); // -// PlayerInventory inv = p.getInventory(); +//// List results = new ArrayList<>(); +//// +//// PlayerInventory inv = p.getInventory(); +//// +//// for ( ItemStack iStack : inv.getStorageContents() ) { +//// if ( iStack != null ) { +//// results.add(iStack); +//// } +//// } +//// for ( ItemStack iStack : inv.getExtraContents() ) { +//// if ( iStack != null ) { +//// results.add(iStack); +//// } +//// } +//// +//// return results; +// } +// private List getPlayerInventory( PlayerInventory inv ) { +// List results = new ArrayList<>(); // -// for ( ItemStack iStack : inv.getStorageContents() ) { +// for ( ItemStack iStack : inv.getContents() ) { // if ( iStack != null ) { // results.add(iStack); // } // } -// for ( ItemStack iStack : inv.getExtraContents() ) { +// +// try { +// for ( ItemStack iStack : inv.getExtraContents() ) { +// if ( iStack != null ) { +// results.add(iStack); +// } +// } +// } catch (NoSuchMethodError e) { +// // Ignore on older versions of spigot... Spigot 1.8.8 does not have this function. +// } +// +// // then remove the armor ItemStacks: +// for ( ItemStack iStack : inv.getArmorContents() ) { // if ( iStack != null ) { -// results.add(iStack); +// results.remove(iStack); // } // } // // return results; - } - private List getPlayerInventory( PlayerInventory inv ) { - List results = new ArrayList<>(); - - for ( ItemStack iStack : inv.getContents() ) { - if ( iStack != null ) { - results.add(iStack); - } - } - - try { - for ( ItemStack iStack : inv.getExtraContents() ) { - if ( iStack != null ) { - results.add(iStack); - } - } - } catch (NoSuchMethodError e) { - // Ignore on older versions of spigot... Spigot 1.8.8 does not have this function. - } - - // then remove the armor ItemStacks: - for ( ItemStack iStack : inv.getArmorContents() ) { - if ( iStack != null ) { - results.remove(iStack); - } - } - - return results; - } +// } - /** - * Get HashMap with all the items of a Player. - * - * Return HashMap of XMaterial-Integer. - * - * @param p - Player. - * - * @return HashMap - XMaterial-Integer. - * */ - private HashMap getHashMapOfPlayerInventories(Player p) { - - HashMap xMaterialIntegerHashMap = new HashMap<>(); - - if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ - - BackpacksUtil backpacksUtil = BackpacksUtil.get(); - if (backpacksUtil.isMultipleBackpacksEnabled()){ - for (String id : backpacksUtil.getBackpacksIDs(p)){ - xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpacksUtil.getBackpack(p, id)); - } - } else { - String id = null; - xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, - backpacksUtil.getBackpack(p, id)); - } - } - - if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ - Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); - if (backpack != null) { - xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpack.getInventory()); - backpack.setChanged(); - backpack.save(); - } - } - - xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, getPlayerInventory( p )); -// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, p.getInventory()); - return xMaterialIntegerHashMap; - } +// /** +// * Get HashMap with all the items of a Player. +// * +// * Return HashMap of XMaterial-Integer. +// * +// * @param p - Player. +// * +// * @return HashMap - XMaterial-Integer. +// * */ +// private HashMap getHashMapOfPlayerInventories(Player p) { +// +// HashMap xMaterialIntegerHashMap = new HashMap<>(); +// +// if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ +// +// BackpacksUtil backpacksUtil = BackpacksUtil.get(); +// if (backpacksUtil.isMultipleBackpacksEnabled()){ +// for (String id : backpacksUtil.getBackpacksIDs(p)){ +// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpacksUtil.getBackpack(p, id)); +// } +// } else { +// String id = null; +// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, +// backpacksUtil.getBackpack(p, id)); +// } +// } +// +// if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ +// Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); +// if (backpack != null) { +// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpack.getInventory()); +// backpack.setChanged(); +// backpack.save(); +// } +// } +// +// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, getPlayerInventory( p )); +//// xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, p.getInventory()); +// return xMaterialIntegerHashMap; +// } /** + * If autosell is enabled, and if user toggleable is enabled, then + * it will check to see if the player has the perm or + * * Get AutoSell Player toggle if available. * If he enabled it, AutoSell will work, otherwise it won't. * If he never used the toggle command, this will return true, just like if he enabled it in the first place. @@ -651,39 +994,92 @@ private HashMap getHashMapOfPlayerInventories(Player p) { * @return boolean. * */ public boolean isPlayerAutoSellEnabled(Player p){ + boolean results = false; + + // If autosell isn't enabled, then return false + if ( isAutoSellEnabled ) { + + results = isSellallPlayerUserToggleEnabled( p ); +// if ( !isAutoSellPerUserToggleablePermEnabled || +// isAutoSellPerUserToggleablePermEnabled && +// p.hasPermission(permissionAutoSellPerUserToggleable)){ +// +// String settingName = "Users." + p.getUniqueId() + ".isEnabled"; +// +// results = sellAllConfig.getString(settingName) == null || +// getBooleanValue( settingName ); +// } + } + + +// if (isAutoSellPerUserToggleablePermEnabled && +// !p.hasPermission(permissionAutoSellPerUserToggleable)){ +// return false; +// } +// +// if (sellAllConfig.getString("Users." + p.getUniqueId() + ".isEnabled") == null){ +// return true; +// } - if (isAutoSellPerUserToggleablePermEnabled && - !p.hasPermission(permissionAutoSellPerUserToggleable)){ - return false; - } - - if (sellAllConfig.getString("Users." + p.getUniqueId() + ".isEnabled") == null){ - return true; - } - - return getBooleanValue("Users." + p.getUniqueId() + ".isEnabled"); +// return getBooleanValue("Users." + p.getUniqueId() + ".isEnabled"); + return results; } - public boolean checkIfPlayerAutosellIsActive(Player p) { - boolean results = true; + /** + *

This function only checks to see if the user can toggle autosell + * on or off. If they can, then it checks the state to see if it's on + * or off. It does not matter if autosell is enabled within sellall or not, + * since this can be used with the auto features autosell too. + *

+ * + * + * + * @param p + * @return + */ + public boolean isSellallPlayerUserToggleEnabled( Player p ) { + boolean results = false; - if ( isAutoSellPerUserToggleable ) { - results = isPlayerAutoSellEnabled(p); + if ( isAutoSellPerUserToggleable ) { + + if ( !isAutoSellPerUserToggleablePermEnabled || + isAutoSellPerUserToggleablePermEnabled && + p.hasPermission(permissionAutoSellPerUserToggleable)){ + + String settingName = "Users." + p.getUniqueId() + ".isEnabled"; + + results = sellAllConfig.getString( settingName ) == null || + getBooleanValue( settingName ); + } } return results; } + +// public boolean checkIfPlayerAutosellIsActive(Player p) { +// boolean results = isAutoSellEnabled; +// +// if ( isAutoSellPerUserToggleable ) { +// results = isPlayerAutoSellEnabled(p); +// } +// +// return results; +// } - /** - * Check if Player is in a disabled world, where he can't use sellall sell. - * - * Return True if he's in a disabled world, False if not. - * - * @return boolean. - * */ - public boolean isPlayerInDisabledWorld(Player p){ - return sellAllDisabledWorlds.contains(p.getWorld().getName()); - } +// /** +// * WARNING: Obsolete because disabled worlds are set in config.yml and +// * the command handler shuts down in those worlds. So it will +// * never run any sellall commands in a diabled world. +// * +// * Check if Player is in a disabled world, where he can't use sellall sell. +// * +// * Return True if he's in a disabled world, False if not. +// * +// * @return boolean. +// * */ +// public boolean isPlayerInDisabledWorld(Player p){ +// return sellAllDisabledWorlds.contains(p.getWorld().getName()); +// } /** * Check if Player is waiting for the end of SellAll Sell Delay. @@ -732,125 +1128,70 @@ public void updateConfig(){ // sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); } - /** - * Init options that will be cached. - * */ - private void initCachedData() { - sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); -// messages = SpigotPrison.getInstance().getMessagesConfig(); - permissionSellAllSell = sellAllConfig.getString("Options.Sell_Permission"); - permissionBypassSign = sellAllConfig.getString("Options.SellAll_By_Sign_Bypass_Permission"); - permissionUseSign = sellAllConfig.getString("Options.SellAll_Sign_Use_Permission"); - permissionGUI = sellAllConfig.getString("Options.GUI_Permission"); - permissionPlayerGUI = sellAllConfig.getString("Options.Player_GUI_Permission"); - permissionPrefixBlocks = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); - permissionAutoSellPerUserToggleable = sellAllConfig.getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission"); - permissionItemTrigger = sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Permission"); - sellAllCurrency = sellAllConfig.getString("Options.SellAll_Currency"); - sellAllSoundSuccess = XSound.matchXSound("Options.Sell_Sound_Success_Name").orElse(XSound.ENTITY_PLAYER_LEVELUP).parseSound(); - sellAllSoundFail = XSound.matchXSound("Options.Sell_Sound_Fail_Name").orElse(XSound.BLOCK_ANVIL_PLACE).parseSound(); - sellAllSignTag = Text.translateAmpColorCodes(sellAllConfig.getString("Options.SellAll_Sign_Visible_Tag") ); - sellAllBlocks = initSellAllBlocks(); - sellAllPrestigeMultipliers = initPrestigeMultipliers(); - sellAllItemTriggers = initSellAllItemTrigger(); - sellAllDisabledWorlds = initSellAllDisabledWorlds(); - defaultMultiplier = Double.parseDouble(sellAllConfig.getString("Options.Multiplier_Default")); - defaultSellAllDelay = Integer.parseInt(sellAllConfig.getString("Options.Sell_Delay_Seconds")); - defaultAutoSellEarningNotificationDelay = Integer.parseInt(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Delay_Seconds")); - isPerBlockPermissionEnabled = getBooleanValue("Options.Sell_Per_Block_Permission_Enabled"); - isAutoSellEnabled = getBooleanValue("Options.Full_Inv_AutoSell"); - isAutoSellNotificationEnabled = getBooleanValue("Options.Full_Inv_AutoSell_Notification"); - isAutoSellEarningNotificationDelayEnabled = getBooleanValue("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled"); - isAutoSellPerUserToggleable = getBooleanValue("Options.Full_Inv_AutoSell_perUserToggleable"); - isAutoSellPerUserToggleablePermEnabled = getBooleanValue("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm"); - isSellAllNotificationEnabled = getBooleanValue("Options.Sell_Notify_Enabled"); - isSellAllSoundEnabled = getBooleanValue("Options.Sell_Sound_Enabled"); - isSellAllBackpackItemsEnabled = getBooleanValue("Options.Sell_Prison_BackPack_Items"); - isSellAllMinesBackpacksPluginEnabled = getBooleanValue("Options.Sell_MinesBackPacks_Plugin_Backpack"); - isSellAllDelayEnabled = getBooleanValue("Options.Sell_Delay_Enabled"); - isSellAllSellPermissionEnabled = getBooleanValue("Options.Sell_Permission_Enabled"); - isSellAllItemTriggerEnabled = getBooleanValue("Options.ShiftAndRightClickSellAll.Enabled"); - isSellAllItemTriggerPermissionEnabled = getBooleanValue("Options.ShiftAndRightClickSellAll.PermissionEnabled"); - isSellAllGUIEnabled = getBooleanValue("Options.GUI_Enabled"); - isSellAllPlayerGUIEnabled = getBooleanValue("Options.Player_GUI_Enabled"); - isSellAllGUIPermissionEnabled = getBooleanValue("Options.GUI_Permission_Enabled"); - isSellAllPlayerGUIPermissionEnabled = getBooleanValue("Options.Player_GUI_Permission_Enabled"); - isSellAllMultiplierEnabled = getBooleanValue("Options.Multiplier_Enabled"); - isSellAllPermissionMultiplierOnlyHigherEnabled = getBooleanValue("Options.Multiplier_Permission_Only_Higher"); - isSellAllSignEnabled = getBooleanValue("Options.SellAll_Sign_Enabled"); - isSellAllSignNotifyEnabled = getBooleanValue("Options.SellAll_Sign_Notify"); - isSellAllSignPermissionToUseEnabled = getBooleanValue("Options.SellAll_Sign_Use_Permission_Enabled"); - isSellAllBySignOnlyEnabled = getBooleanValue("Options.SellAll_By_Sign_Only"); - isSellAllHandEnabled = getBooleanValue("Options.SellAll_Hand_Enabled"); - - isSellAllIgnoreCustomNames = getBooleanValue("Options.SellAll_ignoreCustomNames", false); - } - - private boolean getBooleanValue( String configName ) { - return getBooleanValue(configName, false); - } - private boolean getBooleanValue( String configName, Boolean defaultValue ) { - boolean results = (defaultValue == null ? false : defaultValue.booleanValue() ); - - if ( configName != null ) { - if ( sellAllConfig.isString(configName) ) { - String boolVal = sellAllConfig.getString(configName); - if ( boolVal != null ) { - // Boolean.parseBoolean() also supports yes and no so don't pretest for true/false. - try { - results = Boolean.parseBoolean(boolVal); - } catch (Exception e) { - // Not a boolean value, so ignore and let the "defaut" value stand - } - } - else { - // ignore since it's not a boolean value and let the "default" value stand - } - } - else if ( sellAllConfig.isBoolean(configName) ) { - results = sellAllConfig.getBoolean(configName, results); - } - else { - // Ignore since the config is not boolean or a String that "could" be a boolean - } - } - - return results; - } + /** * Loads sellAll blocks from SellAllConfig.yml * With XMaterials and double values (money). * - * @return HashMap XMaterial-Double. + * @return HashMap * */ - public HashMap initSellAllBlocks(){ + public HashMap initSellAllItems(){ - HashMap sellAllXMaterials = new HashMap<>(); + HashMap sellAllItems = new HashMap<>(); + +// HashMap sellAllXMaterials = new HashMap<>(); if (sellAllConfig.getConfigurationSection("Items") == null){ - return sellAllXMaterials; + return sellAllItems; } for (String key : sellAllConfig.getConfigurationSection("Items").getKeys(false)) { - String itemID = sellAllConfig.getString("Items." + key + ".ITEM_ID"); - - Optional iMatOptional = XMaterial.matchXMaterial(itemID); - XMaterial itemMaterial = iMatOptional.orElse(null); - - if (itemMaterial != null) { - String valueString = sellAllConfig.getString("Items." + key + ".ITEM_VALUE"); - if (valueString != null) { - try { - double value = Double.parseDouble(valueString); - sellAllXMaterials.put(itemMaterial, value); - } catch (NumberFormatException ignored) { - } - } + String itemName = key.trim().toUpperCase(); + + String itemID = sellAllConfig.getString("Items." + itemName + ".ITEM_ID"); + + PrisonBlock pBlock = Prison.get().getPlatform().getPrisonBlock(itemID); + + if ( pBlock != null ) { + String saleValueString = sellAllConfig.getString("Items." + itemName + ".ITEM_VALUE"); + if ( saleValueString != null ) { + + try { + double value = Double.parseDouble(saleValueString); + pBlock.setSalePrice( value ); + } catch (NumberFormatException ignored) { + } + } + + String purchaseValueString = sellAllConfig.getString("Items." + itemName + ".PURCHASE_PRICE"); + if ( purchaseValueString != null ) { + + try { + double value = Double.parseDouble(purchaseValueString); + pBlock.setPurchasePrice( value ); + } catch (NumberFormatException ignored) { + } + } + sellAllItems.put( pBlock.getBlockName().toLowerCase(), pBlock ); } + +// Optional iMatOptional = XMaterial.matchXMaterial(itemID); +// XMaterial itemMaterial = iMatOptional.orElse(null); + +// if (itemMaterial != null) { +// String valueString = sellAllConfig.getString("Items." + key.trim().toUpperCase() + ".ITEM_VALUE"); +// if (valueString != null) { +// try { +// double value = Double.parseDouble(valueString); +// sellAllXMaterials.put(itemMaterial, value); +// } catch (NumberFormatException ignored) { +// } +// } +// } } - return sellAllXMaterials; + return sellAllItems; } /** @@ -866,8 +1207,10 @@ public HashMap initPrestigeMultipliers(){ return prestigeMultipliers; } + // NOTE: They key is the same as the rank name... so no need to read the PRESTIGE_NAME or RANK_NAME: for (String key : sellAllConfig.getConfigurationSection("Multiplier").getKeys(false)){ - prestigeMultipliers.put(sellAllConfig.getString("Multiplier." + key + ".PRESTIGE_NAME"), sellAllConfig.getDouble("Multiplier." + key + ".MULTIPLIER")); + prestigeMultipliers.put( key, + sellAllConfig.getDouble("Multiplier." + key + ".MULTIPLIER")); } return prestigeMultipliers; } @@ -898,13 +1241,13 @@ public ArrayList initSellAllItemTrigger(){ return xMaterials; } - /** - * Get List of names of disabled worlds. - * If a Player is in one of these worlds, he won't be able to use SellAll. - * */ - public List initSellAllDisabledWorlds(){ - return sellAllConfig.getStringList("Options.DisabledWorlds"); - } +// /** +// * Get List of names of disabled worlds. +// * If a Player is in one of these worlds, he won't be able to use SellAll. +// * */ +// public List initSellAllDisabledWorlds(){ +// return sellAllConfig.getStringList("Options.DisabledWorlds"); +// } /** * Add a block to SellAll config. @@ -917,21 +1260,47 @@ public List initSellAllDisabledWorlds(){ * @return boolean. * */ public boolean addSellAllBlock(XMaterial xMaterial, double value){ + + PrisonBlock pBlockKey = Prison.get().getPlatform().getPrisonBlock( xMaterial.name() ); + if ( pBlockKey == null ) { + Output.get().logDebug( "sellall add: invalid block name (%s)", xMaterial.name()); + return false; + } + String key = pBlockKey.getBlockName().toLowerCase(); + + PrisonBlock pBlock = sellAllItems.get( key ); + + // If that is an invalid PrisonBlock, then exit + if ( pBlock != null ) { + Output.get().logDebug( "sellall add: block already exists (%s)", xMaterial.name()); + return false; + } + try { + + String itemName = pBlockKey.getBlockName().toUpperCase(); + File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); + conf.set("Items." + itemName + ".ITEM_ID", xMaterial.name()); + conf.set("Items." + itemName + ".ITEM_VALUE", value); if (getBooleanValue("Options.Sell_Per_Block_Permission_Enabled")) { - conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + String itemPerm = "Items." + itemName + ".ITEM_PERMISSION"; + conf.set( itemPerm, sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); } conf.save(sellAllFile); + updateConfig(); + + pBlockKey.setSalePrice( value ); + sellAllItems.put( pBlockKey.getBlockName().toLowerCase(), pBlockKey ); + } catch (IOException e) { e.printStackTrace(); return false; } - updateConfig(); - sellAllBlocks.put(xMaterial, value); + + +// sellAllBlocks.put(xMaterial, value); return true; } @@ -954,16 +1323,16 @@ public boolean addSellAllBlock(XMaterial xMaterial, double value){ // } /** - * Add Multiplier to SellAll depending on the Prestige Rank (Rank from the prestiges ladder). + * Add Multiplier to SellAll depending on the Rank (Rank from any ladder). * - * Return true if edited with success, false if error or Prestige not found. + * Return true if edited with success, false if error or the rank is not found. * - * @param prestigeName - Name of the Prestige as String. + * @param rankName - Name of the Rank as String. * @param multiplier - Double value. * * @return boolean. * */ - public boolean addPrestigeMultiplier(String prestigeName, double multiplier){ + public boolean addSellallRankMultiplier(String rankName, double multiplier){ PrisonRanks rankPlugin = (PrisonRanks) (Prison.get().getModuleManager() == null ? null : Prison.get().getModuleManager().getModule(PrisonRanks.MODULE_NAME) ); @@ -971,22 +1340,23 @@ public boolean addPrestigeMultiplier(String prestigeName, double multiplier){ return false; } - boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges") != null; - if (!isPrestigeLadder) { - return false; - } + +// boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges") != null; +// if (!isPrestigeLadder) { +// return false; +// } - Rank pRank = rankPlugin.getRankManager().getRank(prestigeName); + Rank rank = rankPlugin.getRankManager().getRank(rankName); - if ( pRank == null ) { + if ( rank == null ) { // Invalid rank! return false; } - if ( !pRank.getLadder().isPrestiges() ) { - // Rank is not in the prestiges ladder: - return false; - } +// if ( !pRank.getLadder().isPrestiges() ) { +// // Rank is not in the prestiges ladder: +// return false; +// } // boolean isInPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").containsRank(rankPlugin.getRankManager().getRank(prestigeName)); // if (!isInPrestigeLadder) { @@ -997,8 +1367,14 @@ public boolean addPrestigeMultiplier(String prestigeName, double multiplier){ File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Multiplier." + pRank.getName() + ".PRESTIGE_NAME", pRank.getName()); - conf.set("Multiplier." + pRank.getName() + ".MULTIPLIER", multiplier); + if ( rank.getLadder().isPrestiges() ) { + conf.set("Multiplier." + rank.getName() + ".PRESTIGE_NAME", rank.getName()); + } + else { + conf.set("Multiplier." + rank.getName() + ".RANK_NAME", rank.getName()); + } + + conf.set("Multiplier." + rank.getName() + ".MULTIPLIER", multiplier); conf.save(sellAllFile); } @@ -1007,7 +1383,7 @@ public boolean addPrestigeMultiplier(String prestigeName, double multiplier){ return false; } - sellAllPrestigeMultipliers.put( pRank.getName(), multiplier); + sellAllPrestigeMultipliers.put( rank.getName(), multiplier); updateConfig(); return true; @@ -1043,7 +1419,7 @@ public boolean addItemTrigger(XMaterial xMaterial){ // /** // * BUG: With Spigot versions less than 1.13 bukkit's Material will not work on all Materials since -// * varient data is stored in the ItemStack. SO must use the XMaterial version of this function. +// * variant data is stored in the ItemStack. SO must use the XMaterial version of this function. // * // * Add SellAll Item Trigger. // * @@ -1067,7 +1443,8 @@ public boolean addItemTrigger(XMaterial xMaterial){ public void addToDelay(Player p){ if (!isPlayerWaitingSellAllDelay(p)){ activePlayerDelay.add(p); - Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromDelay(p), 20L * defaultSellAllDelay); + Bukkit.getScheduler().scheduleSyncDelayedTask( + SpigotPrison.getInstance(), () -> removeFromDelay(p), 20L * defaultSellAllDelay); } } @@ -1088,7 +1465,9 @@ public boolean addToAutoSellNotificationDelay(Player p){ if (!isPlayerWaitingAutoSellNotification(p)){ autoSellEarningsNotificationWaiting.put(p, 0.00); - Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromAutoSellDelayAndNotify(p), 20L * defaultAutoSellEarningNotificationDelay); + Bukkit.getScheduler().scheduleSyncDelayedTask( + SpigotPrison.getInstance(), + () -> removeFromAutoSellDelayAndNotify(p), 20L * defaultAutoSellEarningNotificationDelay); return true; } @@ -1107,61 +1486,61 @@ public void addDelayedEarningAutoSellNotification(Player p, double value){ } } - private HashMap addInventoryToHashMap(HashMap xMaterialIntegerHashMap, Inventory inv) { - - List inventory = new ArrayList<>(); - - for (ItemStack itemStack : inv.getContents()){ - if (itemStack != null){ - inventory.add(itemStack); - } - } - - return addInventoryToHashMap( xMaterialIntegerHashMap, inventory ); - -// for (ItemStack itemStack : inv.getContents()){ +// private HashMap addInventoryToHashMap(HashMap xMaterialIntegerHashMap, Inventory inv) { +// +// List inventory = new ArrayList<>(); +// +// for (ItemStack itemStack : inv.getContents()){ // if (itemStack != null){ -// XMaterial xMaterial = getXMaterialOrLapis(itemStack); -// -// if ( xMaterial != null ) { -// -// if (xMaterialIntegerHashMap.containsKey(xMaterial)){ -// xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); -// } -// else { -// xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); -// } -// } -// } -// } -// return xMaterialIntegerHashMap; - } - - private HashMap addInventoryToHashMap(HashMap xMaterialIntegerHashMap, List inv) { - for (ItemStack itemStack : inv){ - if (itemStack != null){ - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - - if ( xMaterial != null ) { - - if (xMaterialIntegerHashMap.containsKey(xMaterial)){ - xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); - } - else { - xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); - } - } - } - } - return xMaterialIntegerHashMap; - } +// inventory.add(itemStack); +// } +// } +// +// return addInventoryToHashMap( xMaterialIntegerHashMap, inventory ); +// +//// for (ItemStack itemStack : inv.getContents()){ +//// if (itemStack != null){ +//// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +//// +//// if ( xMaterial != null ) { +//// +//// if (xMaterialIntegerHashMap.containsKey(xMaterial)){ +//// xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); +//// } +//// else { +//// xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); +//// } +//// } +//// } +//// } +//// return xMaterialIntegerHashMap; +// } + +// private HashMap addInventoryToHashMap(HashMap xMaterialIntegerHashMap, List inv) { +// for (ItemStack itemStack : inv){ +// if (itemStack != null){ +// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +// +// if ( xMaterial != null ) { +// +// if (xMaterialIntegerHashMap.containsKey(xMaterial)){ +// xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); +// } +// else { +// xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); +// } +// } +// } +// } +// return xMaterialIntegerHashMap; +// } /** * Check if Player meets requirements to use SellAll. * * This will return true if everything is meet, False if even only isn't. * What will be checked is: - * - Is in a world where SellAll Sell isn't locked by config. + * - OBSOLETE: ~Is in a world where SellAll Sell isn't locked by config.~ * - Check if SellAll Signs and SellAll by Sign only is enabled and Player isn't selling through a Sign right now or * doesn't have the bypass permission (To tell to this method if Player is selling through a sign, please set the boolean * parameter to true). @@ -1179,9 +1558,9 @@ public boolean canPlayerSell(Player p, boolean isUsingSign){ return false; } - if (isPlayerInDisabledWorld(p)){ - return false; - } +// if (isPlayerInDisabledWorld(p)){ +// return false; +// } if (isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !isUsingSign && !p.hasPermission(permissionBypassSign)){ return false; @@ -1207,26 +1586,54 @@ public boolean canPlayerSell(Player p, boolean isUsingSign){ * */ public boolean editPrice(XMaterial xMaterial, double value){ + PrisonBlock pBlockKey = Prison.get().getPlatform().getPrisonBlock( xMaterial.name() ); + String key = pBlockKey.getBlockName().toLowerCase(); + + PrisonBlock pBlock = sellAllItems.get( key ); + // Do not allow an edit price if the material does not exist, or if the value has not changed: - if (!sellAllBlocks.containsKey(xMaterial) && sellAllBlocks.get(xMaterial) != value ){ + if ( pBlock == null ){ + + Output.get().logDebug( "sellall edit: item does not exist in shop so it cannot be edited (%s)", pBlockKey.getBlockName()); return false; } + if ( pBlock.getSalePrice() == value ){ + DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + Output.get().logDebug( "sellall edit: No change in price (%s:%s)", + pBlockKey.getBlockName(), dFmt.format(value) ); + return false; + } + + pBlock.setSalePrice( value ); try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); + + String itemName = key.toUpperCase(); + conf.set("Items." + itemName + ".ITEM_ID", key ); + conf.set("Items." + itemName + ".ITEM_VALUE", value); + + if ( pBlock.getPurchasePrice() != null ) { + + conf.set("Items." + itemName + ".PURCHASE_PRICE", pBlock.getPurchasePrice().doubleValue() ); + } + if (getBooleanValue("Options.Sell_Per_Block_Permission_Enabled")) { - conf.set("Items." + xMaterial + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + conf.set("Items." + itemName + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + itemName ); } conf.save(sellAllFile); + + // Update only if successful + updateConfig(); } catch (IOException e) { e.printStackTrace(); return false; } - updateConfig(); - sellAllBlocks.put(xMaterial, value); + + // pBlock is still in the sellAllItems collection so no need to readd it +// sellAllBlocks.put(xMaterial, value); + return true; } @@ -1261,7 +1668,7 @@ public boolean editPrestigeMultiplier(String prestigeName, double multiplier) { return false; } - return addPrestigeMultiplier(prestigeName, multiplier); + return addSellallRankMultiplier(prestigeName, multiplier); } /** @@ -1275,21 +1682,29 @@ public boolean editPrestigeMultiplier(String prestigeName, double multiplier) { * */ public boolean removeSellAllBlock(XMaterial xMaterial){ - if (!sellAllBlocks.containsKey(xMaterial)){ + PrisonBlock pBlockKey = Prison.get().getPlatform().getPrisonBlock( xMaterial.name() ); + String key = pBlockKey.getBlockName().toLowerCase(); + + PrisonBlock pBlock = sellAllItems.get( key ); + + if ( pBlock == null ){ return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name(), null); + conf.set("Items." + pBlock.getBlockName().toUpperCase(), null); conf.save(sellAllFile); + + updateConfig(); } catch (IOException e) { e.printStackTrace(); return false; } - updateConfig(); - sellAllBlocks.remove(xMaterial); + + sellAllItems.remove( key ); +// sellAllBlocks.remove(xMaterial); return true; } @@ -1310,29 +1725,29 @@ public boolean removeSellAllBlock(XMaterial xMaterial){ // } /** - * Remove a Prestige Multiplier by name. + * Remove a Rank Multiplier by name. * * Return true if success, false if error or not found. * - * @param prestigeName - String. + * @param rankName - String. * * @return boolean. * */ - public boolean removePrestigeMultiplier(String prestigeName){ + public boolean removeSellallRankMultiplier(String rankName){ - if (!sellAllPrestigeMultipliers.containsKey(prestigeName)){ + if (!sellAllPrestigeMultipliers.containsKey(rankName)){ return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Multiplier." + prestigeName, null); + conf.set("Multiplier." + rankName, null); conf.save(sellAllFile); } catch (IOException e) { return false; } - sellAllPrestigeMultipliers.remove(prestigeName); + sellAllPrestigeMultipliers.remove(rankName); updateConfig(); return true; } @@ -1383,197 +1798,254 @@ public boolean removeItemTrigger(XMaterial xMaterial){ // return removeItemTrigger(XMaterial.matchXMaterial(material)); // } - /** - * Remove Sellable Blocks from HashMap of XMaterial-Integer given as a parameter. - * NOTE: If there aren't blocks in the SellAll shop, nothing will change. - * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use - * the getSellAllSellMoney method. - * - * @param p - Player. - * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). - * - * - * @return HashMap - XMaterial-Integer. - * */ - public HashMap removeSellableItems(Player p, HashMap xMaterialIntegerHashMap){ - - if (sellAllBlocks.isEmpty()){ - return xMaterialIntegerHashMap; - } - - /* Not necessary now, as this only removes what's sellable, this should be checked in another place before. - if (isPlayerInDisabledWorld(p)){ - return xMaterialIntegerHashMap; - } - */ - - for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ - if (sellAllBlocks.containsKey(xMaterialIntegerEntry.getKey())){ - // This is stupid but right now I'm too confused, sorry. - if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterialIntegerEntry.getKey().name())){ - // Nothing will happen. - } else { - xMaterialIntegerHashMap.remove(xMaterialIntegerEntry.getKey()); - } - } - } - - return xMaterialIntegerHashMap; - } - - /** - * Remove Sellable Blocks from ArrayList of ItemStacks given as a parameter. - * NOTE: If there aren't blocks in the SellAll shop, nothing will change. - * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use - * the getSellAllSellMoney method. - * - * @param p - Player. - * @param itemStacks - ItemStacks. - * - * @return ArrayList - ItemStacks. - * */ - public ArrayList removeSellableItems(Player p, ArrayList itemStacks){ - - if (sellAllBlocks.isEmpty()){ - return itemStacks; - } - - HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); - - xMaterialIntegerHashMap = removeSellableItems(p, xMaterialIntegerHashMap); - - ArrayList newItemStacks = new ArrayList<>(); - for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ - - // WARNING: Cannot convert XMaterial to a Material then ItemStack or it will fail on variants - // for spigot versions less than 1.13: - - ItemStack iStack = xMaterialIntegerEntry.getKey().parseItem(); - if ( iStack != null ) { - iStack.setAmount( xMaterialIntegerEntry.getValue() ); - newItemStacks.add( iStack ); - } - -// Material material = xMaterialIntegerEntry.getKey().parseMaterial(); -// if (material != null) { -// newItemStacks.add(new ItemStack(material, xMaterialIntegerEntry.getValue())); +// /** +// * Remove Sellable Blocks from HashMap of XMaterial-Integer given as a parameter. +// * NOTE: If there aren't blocks in the SellAll shop, nothing will change. +// * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use +// * the getSellAllSellMoney method. +// * +// * @param p - Player. +// * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). +// * +// * +// * @return HashMap - XMaterial-Integer. +// * */ +// public HashMap removeSellableItems(Player p, HashMap xMaterialIntegerHashMap){ +// +// if (sellAllItems.isEmpty()){ +// return xMaterialIntegerHashMap; +// } +// +// /* Not necessary now, as this only removes what's sellable, this should be checked in another place before. +// if (isPlayerInDisabledWorld(p)){ +// return xMaterialIntegerHashMap; +// } +// */ +// +// for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ +// +// XMaterial xMaterial = xMaterialIntegerEntry.getKey(); +// PrisonBlock pBlockKey = Prison.get().getPlatform().getPrisonBlock( xMaterial.name() ); +// String key = pBlockKey.getBlockName(); +// +// PrisonBlock pBlock = sellAllItems.get( key ); +// +// if ( pBlock != null ){ +// // This is stupid but right now I'm too confused, sorry. +// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + pBlock.getBlockName().toUpperCase() )){ +// // Nothing will happen. +// } else { +// xMaterialIntegerHashMap.remove( xMaterial ); +// } // } - } +// } +// +// return xMaterialIntegerHashMap; +// } - return newItemStacks; - } - - /** - * Remove Sellable blocks from an Inventory of a Player. - * - * Return an Inventory with the unsold items. - * - * @param p - Player. - * @param inv - Inventory. - * - * @return inv - Inventory. - * */ - public Inventory removeSellableItems(Player p, Inventory inv){ - if (sellAllBlocks.isEmpty()){ - return inv; - } - - SpigotCompatibility.getInstance().getItemInOffHand( p ); - - List removeable = new ArrayList<>(); - - for (ItemStack itemStack : inv.getContents()){ - if (itemStack != null){ - try { - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - - if ( xMaterial != null && sellAllBlocks.containsKey(xMaterial)) { - if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())) { - // Nothing will change. - } else { - removeable.add( itemStack ); -// inv.remove(itemStack); - } - } - } catch (IllegalArgumentException ignored){} - } - } - - for ( ItemStack remove : removeable ) - { - inv.remove(remove); - } - - return inv; - } +// /** +// * Remove Sellable Blocks from ArrayList of ItemStacks given as a parameter. +// * NOTE: If there aren't blocks in the SellAll shop, nothing will change. +// * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use +// * the getSellAllSellMoney method. +// * +// * @param p - Player. +// * @param itemStacks - ItemStacks. +// * +// * @return ArrayList - ItemStacks. +// * */ +// private ArrayList removeSellableItems(Player p, ArrayList itemStacks){ +// +// if (sellAllItems.isEmpty()){ +// return itemStacks; +// } +// +// HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); +// +// xMaterialIntegerHashMap = removeSellableItems(p, xMaterialIntegerHashMap); +// +// ArrayList newItemStacks = new ArrayList<>(); +// for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ +// +// // WARNING: Cannot convert XMaterial to a Material then ItemStack or it will fail on variants +// // for spigot versions less than 1.13: +// +// ItemStack iStack = xMaterialIntegerEntry.getKey().parseItem(); +// if ( iStack != null ) { +// iStack.setAmount( xMaterialIntegerEntry.getValue() ); +// newItemStacks.add( iStack ); +// } +// +//// Material material = xMaterialIntegerEntry.getKey().parseMaterial(); +//// if (material != null) { +//// newItemStacks.add(new ItemStack(material, xMaterialIntegerEntry.getValue())); +//// } +// } +// +// return newItemStacks; +// } - public void removeSellableItemsInOffHand(Player p){ - - - ItemStack itemStack = SpigotCompatibility.getInstance().getItemInOffHand( p ); - - if ( itemStack != null ) { - - if (itemStack != null){ - try { - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - - if ( xMaterial != null && sellAllBlocks.containsKey(xMaterial)) { - if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())) { - // Nothing will change. - } - else { - - SpigotPlayerInventory spInventory = new SpigotPlayerInventory( p.getInventory() ) ; - SpigotItemStack sItemStack = new SpigotItemStack( new ItemStack( Material.AIR ) ); - - SpigotCompatibility.getInstance().setItemStackInOffHand( spInventory, sItemStack ); - - } - } - } catch (IllegalArgumentException ignored){} - } - } - +// /** +// * Remove Sellable blocks from an Inventory of a Player. +// * +// * Return an Inventory with the unsold items. +// * +// * @param p - Player. +// * @param inv - Inventory. +// * +// * @return inv - Inventory. +// * */ +// private Inventory removeSellableItems(Player p, Inventory inv){ +// if (sellAllItems.isEmpty()){ +// return inv; +// } +// +// // ?? why? +//// SpigotCompatibility.getInstance().getItemInOffHand( p ); +// +// List removeable = new ArrayList<>(); +// +// SpigotInventory sInv = new SpigotInventory( inv ); +// +// for (tech.mcprison.prison.internal.ItemStack itemStack : sInv.getItems()) { +// if (itemStack != null){ +// try { +// PrisonBlock pBlock = itemStack.getMaterial(); +// +// +//// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +// +// if ( pBlock != null && sellAllItems.containsKey( pBlock.getBlockName() )) { +// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + pBlock.getBlockName().toUpperCase() )) { +// // Nothing will change. +// } else { +// removeable.add( ((SpigotItemStack) itemStack).getBukkitStack() ); +//// inv.remove(itemStack); +// } +// } +// } catch (IllegalArgumentException ignored){} +// } +// } +// +//// for (ItemStack itemStack : inv.getContents()){ +//// if (itemStack != null){ +//// try { +//// PrisonBlock +//// +//// +//// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +//// +//// if ( xMaterial != null && sellAllBlocks.containsKey(xMaterial)) { +//// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())) { +//// // Nothing will change. +//// } else { +//// removeable.add( itemStack ); +////// inv.remove(itemStack); +//// } +//// } +//// } catch (IllegalArgumentException ignored){} +//// } +//// } +// +// for ( ItemStack remove : removeable ) +// { +// inv.remove(remove); +// } +// +// return inv; +// } - } +// private void removeSellableItemsInOffHand(Player p){ +// +// +// +// SpigotItemStack sItemStack = SpigotCompatibility.getInstance().getPrisonItemInOffHand( p ); +// +// if ( sItemStack != null ) { +// +// PrisonBlock pBlock = sItemStack.getMaterial(); +// +// if ( pBlock != null && sellAllItems.containsKey( pBlock.getBlockName() )) { +// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + pBlock.getBlockName().toUpperCase() )) { +// // Nothing will change. +// } else { +// +// SpigotPlayer sPlayer = new SpigotPlayer( p ); +// SpigotPlayerInventory spInventory = (SpigotPlayerInventory) sPlayer.getInventory(); +// +// SpigotItemStack sItemStackAir = (SpigotItemStack) PrisonBlock.AIR.getItemStack( 1 ); +// +// SpigotCompatibility.getInstance().setItemStackInOffHand( spInventory, sItemStackAir ); +// } +// } +// } +// +// +// +//// ItemStack itemStack = SpigotCompatibility.getInstance().getItemInOffHand( p ); +//// +//// if ( itemStack != null ) { +//// +//// if (itemStack != null){ +//// try { +//// XMaterial xMaterial = getXMaterialOrLapis(itemStack); +//// +//// if ( xMaterial != null && sellAllBlocks.containsKey(xMaterial)) { +//// if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())) { +//// // Nothing will change. +//// } +//// else { +//// +//// SpigotPlayerInventory spInventory = new SpigotPlayerInventory( p.getInventory() ) ; +//// SpigotItemStack sItemStack = new SpigotItemStack( new ItemStack( Material.AIR ) ); +//// +//// SpigotCompatibility.getInstance().setItemStackInOffHand( spInventory, sItemStack ); +//// +//// } +//// } +//// } catch (IllegalArgumentException ignored){} +//// } +//// } +// +// +// } - /** - * Remove Sellable blocks from all Player inventories directly hooked. - * - * @param p - Player. - * */ - public void removeSellableItems(Player p){ - - if (sellAllBlocks.isEmpty()){ - return; - } - - if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ - BackpacksUtil backpacksUtil = BackpacksUtil.get(); - if (backpacksUtil.isMultipleBackpacksEnabled()){ - for (String id : backpacksUtil.getBackpacksIDs(p)){ - backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p, id)), id); - } - } else { - String id = null; - backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p, id)), id); - } - } - - if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ - Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); - if (backpack != null) { - removeSellableItems(p, backpack.getInventory()); - backpack.setChanged(); - backpack.save(); - } - } - - removeSellableItems(p, p.getInventory()); - - removeSellableItemsInOffHand( p ); - } +// /** +// * Remove Sellable blocks from all Player inventories directly hooked. +// * +// * @param p - Player. +// * */ +// private void removeSellableItems(Player p){ +// +// if (sellAllItems.isEmpty()){ +// return; +// } +// +// if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ +// BackpacksUtil backpacksUtil = BackpacksUtil.get(); +// if (backpacksUtil.isMultipleBackpacksEnabled()){ +// for (String id : backpacksUtil.getBackpacksIDs(p)){ +// backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p, id)), id); +// } +// } else { +// String id = null; +// backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p, id)), id); +// } +// } +// +// if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ +// Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); +// if (backpack != null) { +// removeSellableItems(p, backpack.getInventory()); +// backpack.setChanged(); +// backpack.save(); +// } +// } +// +// removeSellableItems(p, p.getInventory()); +// +// removeSellableItemsInOffHand( p ); +// } /** * Remove Player from delay. @@ -1597,9 +2069,19 @@ public void removeFromAutoSellDelayAndNotify(Player p){ String message = sellallAmountEarnedMsg( amt ); + SpigotPlayer sPlayer = new SpigotPlayer(p); + + if ( isSellAllNotificationByActionBar ) { + + sPlayer.setActionBar( message ); + } + else { + + Output.get().send( sPlayer, message ); + } + // String message = messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + amt; // new SpigotPlayer(p).setActionBar( message ); - Output.get().send( new SpigotPlayer(p), message ); } autoSellEarningsNotificationWaiting.remove(p); } @@ -1829,19 +2311,50 @@ public boolean setDelay(int delay){ * * @return boolean If successful * */ - public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, - boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll){ - return sellAllSell( p, isUsingSign, completelySilent, notifyPlayerEarned, notifyPlayerDelay, - notifyPlayerEarningDelay, playSoundOnSellAll, null ); + public boolean sellAllSell(Player p, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll) { + return sellAllSell( p, isUsingSign, completelySilent, + notifyPlayerEarned, notifyPlayerDelay, + notifyPlayerEarningDelay, playSoundOnSellAll, + true, + null ); + } + + public boolean sellAllSell(Player p, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll, + List amounts ) { + + return sellAllSell( p, isUsingSign, completelySilent, + notifyPlayerEarned, notifyPlayerDelay, + notifyPlayerEarningDelay, playSoundOnSellAll, + true, + amounts ); } - public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, - boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll, List amounts ){ + + public boolean sellAllSell(Player p, + boolean isUsingSign, + boolean completelySilent, + boolean notifyPlayerEarned, + boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, + boolean playSoundOnSellAll, + boolean notifyNothingToSell, + List amounts ) { if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ if (!completelySilent) { sellallCanOnlyUseSignsMsg( new SpigotCommandSender(p) ); -// Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_sign_only)); } return false; } @@ -1850,23 +2363,36 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile if (notifyPlayerDelay && !completelySilent) { sellallRateLimitExceededMsg( new SpigotCommandSender(p) ); -// Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_wait)); } return false; } - if (sellAllBlocks.isEmpty()){ + if (sellAllItems.isEmpty()){ if (!completelySilent){ sellallShopIsEmptyMsg( new SpigotCommandSender(p) ); -// Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_empty)); } return false; } + + + + double money = 0; + double multiplier = getPlayerMultiplier(p); + + List soldItems = sellPlayerItems(p); + + for (SellAllData soldItem : soldItems) { + money += soldItem.getTransactionAmount(); + } + + SellAllData.debugItemsSold( soldItems, new SpigotPlayer( p ), multiplier ); + + //TODO inventory access: getHashMapOfPlayerInventories() && removeSellableItems(p, p.getInventory()); - double money = getSellMoney(p); - if (money != 0){ +// double money = getSellMoney(p); + if (money != 0) { if ( amounts != null ) { @@ -1879,7 +2405,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile //TODO inventory access: getHashMapOfPlayerInventories() && removeSellableItems(p, p.getInventory()); - removeSellableItems(p); + //removeSellableItems(p); SpigotPlayer sPlayer = new SpigotPlayer(p); @@ -1906,39 +2432,49 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile } if (notifyPlayerEarningDelay && isAutoSellEarningNotificationDelayEnabled){ - if (!isPlayerWaitingAutoSellNotification(p)){ + if (!isPlayerWaitingAutoSellNotification(p)) { addToAutoSellNotificationDelay(p); } addDelayedEarningAutoSellNotification(p, money); - } else if (notifyPlayerEarned){ + } + else if (notifyPlayerEarned) { DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); String amt = fFmt.format( money ); String message = sellallAmountEarnedMsg( amt ); + if ( isSellAllNotificationByActionBar ) { + sPlayer.setActionBar( message ); + } + else { + + Output.get().send( sPlayer, message ); + } + // String message = messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + amt; // new SpigotPlayer(p).setActionBar( message ); - Output.get().send( new SpigotPlayer(p), message ); +// Output.get().send( sPlayer, message ); } } return true; - } else { - if (!completelySilent){ + } + else { + if (!completelySilent && notifyNothingToSell) { if (isSellAllSoundEnabled && playSoundOnSellAll) { p.playSound(p.getLocation(), sellAllSoundFail, 3, 1); } sellallYouHaveNothingToSellMsg( new SpigotCommandSender(p) ); -// Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_nothing_sellable)); } return false; } } - - /** + + + /** *

This function enables the selling of just one ItemStack and can be used outside of * the player's inventory, such as processing the drops of tens of thousands of blocks * worth of drops. This would be much faster than processing the player's inventory. @@ -1963,7 +2499,24 @@ public double sellAllSell(Player p, SpigotItemStack itemStack, // long tPoint4 = tPoint1; // long tPoint5 = tPoint1; - double money = getSellMoney(p, itemStack); + + double money = 0; + double multiplier = getPlayerMultiplier(p); + + List soldItems = new ArrayList<>(); + + SellAllData sad = sellItemStack( itemStack, multiplier ); + if ( sad != null ) { + soldItems.add(sad); + } + + for (SellAllData soldItem : soldItems) { + money += soldItem.getTransactionAmount(); + } + + SellAllData.debugItemsSold(soldItems, new SpigotPlayer(p), multiplier); + +// double money = getSellMoney(p, itemStack); // tPoint2 = System.nanoTime(); @@ -2001,9 +2554,17 @@ else if (notifyPlayerEarned){ String message = sellallAmountEarnedMsg( amt ) ; + if ( isSellAllNotificationByActionBar ) { + sPlayer.setActionBar( message ); + } + else { + + Output.get().send( sPlayer, message ); + } + // String message = messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + amt; // new SpigotPlayer(p).setActionBar( message ); - Output.get().send( new SpigotPlayer(p), message ); +// Output.get().send( sPlayer, message ); } } @@ -2058,7 +2619,11 @@ else if (notifyPlayerEarned){ * * @return boolean. * */ - public ArrayList sellAllSell(Player p, ArrayList itemStacks, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll, boolean sellInputArrayListOnly){ + public ArrayList sellAllSell(Player p, ArrayList itemStacks, + boolean isUsingSign, boolean completelySilent, + boolean notifyPlayerEarned, boolean notifyPlayerDelay, + boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll, + boolean sellInputArrayListOnly){ if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ if (!completelySilent) { @@ -2077,7 +2642,7 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack return itemStacks; } - if (sellAllBlocks.isEmpty()){ + if (sellAllItems.isEmpty()){ if (!completelySilent){ sellallShopIsEmptyMsg( new SpigotCommandSender(p) ); @@ -2086,17 +2651,58 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack return itemStacks; } - double arrayListMoney = getSellMoney(p, itemStacks); - if (arrayListMoney != 0.00){ - itemStacks = removeSellableItems(p, itemStacks); + + double money = 0; + double multiplier = getPlayerMultiplier(p); + + List soldItems = new ArrayList<>(); + + ArrayList itemsNotSold = new ArrayList<>(); + + for (ItemStack itemStack : itemStacks ) { + + SellAllData sad = sellItemStack( new SpigotItemStack( itemStack ), multiplier ); + if ( sad != null ) { + soldItems.add(sad); + } + else { + itemsNotSold.add( itemStack ); + } + } + + // "return" all items not sold: + itemStacks.clear(); + itemStacks.addAll( itemsNotSold ); + + + // Sell the player's inventory if requested + if ( !sellInputArrayListOnly ) { + soldItems.addAll( sellPlayerItems(p) ); } + + for (SellAllData soldItem : soldItems) { + money += soldItem.getTransactionAmount(); + } - double money; - if (sellInputArrayListOnly){ - money = arrayListMoney; - } else { - money = getSellMoney(p) + arrayListMoney; - } + + SellAllData.debugItemsSold( soldItems, new SpigotPlayer( p ), multiplier ); + + + // Sell only the itemStacks and then remove the ones that were sold: +// double arrayListMoney = getSellMoney(p, itemStacks); +// if (arrayListMoney != 0.00){ +// itemStacks = removeSellableItems(p, itemStacks); +// } + +// double money; +// +// // If to include the player's inventory, then add that too: +// if (sellInputArrayListOnly){ +// money = arrayListMoney; +// } else { +// // Add the players inventory +// money = getSellMoney(p) + arrayListMoney; +// } if (money != 0){ @@ -2104,9 +2710,9 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); if (sellAllCurrency != null && sellAllCurrency.equalsIgnoreCase("default")) sellAllCurrency = null; - if (!sellInputArrayListOnly) { - removeSellableItems(p); - } +// if (!sellInputArrayListOnly) { +// removeSellableItems(p); +// } rankPlayer.addBalance(sellAllCurrency, money); if (isSellAllDelayEnabled){ @@ -2130,9 +2736,16 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack String message = sellallAmountEarnedMsg( amt ); + if ( isSellAllNotificationByActionBar ) { + sPlayer.setActionBar( message ); + } + else { + + Output.get().send( sPlayer, message ); + } + // String message = messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + amt; // new SpigotPlayer(p).setActionBar( message ); - Output.get().send( new SpigotPlayer(p), message ); } } @@ -2149,7 +2762,9 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack return itemStacks; } - /** + + + /** * Open SellAll GUI to the specified Player. * NOTE: SellAll GUI must be enabled from the config or nothing will happen. * NOTE #2: A Player if admin will open another GUI if meets requirements, if not it will try to check diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventData.java index 39a9a92b9..deb6b8661 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventData.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventData.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.util.Text; public class SlimeBlockFunEventData { @@ -24,10 +25,15 @@ public class SlimeBlockFunEventData { private double recordBoost = 0.0; private double recordVelocity = 0.0; + private boolean displayMessages = false; + + private final int worldHeight; + + private DecimalFormat sFmt = Prison.get().getDecimalFormat("#,##0.0"); private DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - public SlimeBlockFunEventData( Long playerUUIDLSB, double y ) { + public SlimeBlockFunEventData( Long playerUUIDLSB, double y, int worldHeight ) { super(); this.playerUUIDLSB = playerUUIDLSB; @@ -38,6 +44,11 @@ public SlimeBlockFunEventData( Long playerUUIDLSB, double y ) { this.jumping = false; this.recordHeight = 0.0; this.recordY = 0.0; + + this.worldHeight = worldHeight; + + this.displayMessages = SpigotPrison.getInstance().getConfig() + .getBoolean("slime-fun.display-messages", true); } public void addJumpEvent( double y, double boost, double velocityY ) { @@ -68,11 +79,16 @@ public void inAir( double currentY, Player player ) { } else if ( currentY < getMaxY() ) { - if ( currentY >= 255 ) { - player.sendMessage( "SlimeFun: You jumped out of the world! " + - " y= " + dFmt.format( currentY )); + if ( isDisplayMessages() ) { + + if ( currentY >= getWorldHeight() ) { +// if ( currentY >= 255 ) { + player.sendMessage( "SlimeFun: You jumped out of the world! " + + " y= " + dFmt.format( currentY )); + } + } - + // Just starting to go back down!! // Stop recording the jump: atTopOfJump( player ); @@ -102,26 +118,29 @@ private void atTopOfJump( Player player ) setRecordVelocity( getVelocityY() ); } - String message1 = Text.translateAmpColorCodes( - String.format("&a%s &3Height: &7%s &a%s &3maxY: &7%s &a%s", - (recY || recH || recB || recV ? "&6.-=New=-." : "__Slime__"), - sFmt.format(height), - (recH ? "&6" : "" ) + sFmt.format( getRecordHeight() ), - sFmt.format(getMaxY()), - (recY ? "&6" : "" ) + sFmt.format( getRecordY()) - )); - - String message2 = Text.translateAmpColorCodes( - String.format("&a%s &3Boost: &7%s &b%s &a%s &3Velocity: &7%s &a%s", - (recY || recH || recB || recV ? "&6-Record!-" : "__Fun!!__"), - - dFmt.format(getBoost()), Integer.toString( getBoostCount()), - (recB ? "&6" : "" ) + dFmt.format( getRecordBoost() ), - dFmt.format(getVelocityY()), - (recV ? "&6" : "" ) + dFmt.format(getRecordVelocity()) - )); - player.sendMessage( message1 ); - player.sendMessage( message2 ); + if ( isDisplayMessages() ) { + + String message1 = Text.translateAmpColorCodes( + String.format("&a%s &3Height: &7%s &a%s &3maxY: &7%s &a%s", + (recY || recH || recB || recV ? "&6.-=New=-." : "__Slime__"), + sFmt.format(height), + (recH ? "&6" : "" ) + sFmt.format( getRecordHeight() ), + sFmt.format(getMaxY()), + (recY ? "&6" : "" ) + sFmt.format( getRecordY()) + )); + + String message2 = Text.translateAmpColorCodes( + String.format("&a%s &3Boost: &7%s &b%s &a%s &3Velocity: &7%s &a%s", + (recY || recH || recB || recV ? "&6-Record!-" : "__Fun!!__"), + + dFmt.format(getBoost()), Integer.toString( getBoostCount()), + (recB ? "&6" : "" ) + dFmt.format( getRecordBoost() ), + dFmt.format(getVelocityY()), + (recV ? "&6" : "" ) + dFmt.format(getRecordVelocity()) + )); + player.sendMessage( message1 ); + player.sendMessage( message2 ); + } // Reset key values: setJumping( false ); @@ -229,5 +248,16 @@ public double getRecordVelocity() { public void setRecordVelocity( double recordVelocity ) { this.recordVelocity = recordVelocity; } + + public boolean isDisplayMessages() { + return displayMessages; + } + public void setDisplayMessage(boolean displayMessages) { + this.displayMessages = displayMessages; + } + + public int getWorldHeight() { + return worldHeight; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java index 8b4f44971..7045a84d4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java @@ -1,11 +1,13 @@ package tech.mcprison.prison.spigot.slime; import java.text.DecimalFormat; +import java.util.Set; import java.util.TreeMap; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -19,21 +21,69 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; +import tech.mcprison.prison.spigot.spiget.BluesSemanticVersionData; public class SlimeBlockFunEventListener implements Listener { private boolean enabled = false; - + private final TreeMap playerSlimeJumpCache; + + private final TreeMap boosters; + private final int worldHeight; + public SlimeBlockFunEventListener() { super(); this.playerSlimeJumpCache = new TreeMap<>(); - this.enabled = SpigotPrison.getInstance().getConfig().getBoolean("slime-fun"); + this.boosters = new TreeMap<>(); + + boolean enabled1 = SpigotPrison.getInstance().getConfig().getBoolean("slime-fun"); + boolean enabled2 = SpigotPrison.getInstance().getConfig().getBoolean("slime-fun.enabled"); + + this.enabled = enabled1 || enabled2; + + + ConfigurationSection mults = SpigotPrison.getInstance().getConfig().getConfigurationSection( "slime-fun.boosters" ); + + if ( mults != null ) { + + Set keys = mults.getKeys( false ); + + for (String key : keys) { + double mult = mults.getDouble( key ); + + if ( mult != 0 ) { + getBoosters().put( key.toLowerCase(), mult ); + } + } + } + else { + // No config is setup, so use these defaults: + getBoosters().put( "diamond_pickkaxe", 3.0 ); + getBoosters().put( "gold_pickaxe", 2.85 ); + getBoosters().put( "iron_pickaxe", 2.85 ); + getBoosters().put( "stone_pickaxe", 2.85 ); + getBoosters().put( "wood_pickaxe", 2.85 ); + getBoosters().put( "diamond_block", 1.65 ); + getBoosters().put( "gold_block", 1.45 ); + getBoosters().put( "iron_block", 1.20 ); + } + + + BluesSemanticVersionData bsvd = new BluesSemanticVersionData( Prison.get().getMinecraftVersion() ); + BluesSemanticVersionData bsvd18 = new BluesSemanticVersionData("1.18"); + + if ( bsvd.compareTo(bsvd18) >= 0 ) { + this.worldHeight = 320; + } + else { + this.worldHeight = 256; + } } @@ -91,11 +141,16 @@ else if ( velY > 0.2 ) { // Record player's System time stamp on Jump Boost: // Add player jump data to the cache: if ( !getPlayerSlimeJumpCache().containsKey( playerUUIDLSB ) ) { - SlimeBlockFunEventData moveEventData = new SlimeBlockFunEventData( playerUUIDLSB, loc.getY() ); + SlimeBlockFunEventData moveEventData = + new SlimeBlockFunEventData( playerUUIDLSB, loc.getY(), getWorldHeight() ); getPlayerSlimeJumpCache().put( playerUUIDLSB, moveEventData ); - player.sendMessage( "SlimeFun: Use at your own risk. Jumpping out of the " + - "world may crash the server." ); +// if ( moveEventData.isDisplayMessage() ) { +// +// player.sendMessage( "SlimeFun: Use at your own risk. Jumpping out of the " + +// "world may crash the server." ); +// } + } getPlayerSlimeJumpCache().get( playerUUIDLSB ) @@ -132,10 +187,18 @@ private Vector calculateVelocityY( double boost, Vector velocityOriginal, Player if ( velocityY > 1024.0 ) { - DecimalFormat f4Fmt = Prison.get().getDecimalFormat("#,##0.0000"); - player.sendMessage( "SlimeFun: Exceeded max velocity!! velY:" + + // Record player's System time stamp on Jump Boost: + Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); + + if ( getPlayerSlimeJumpCache().containsKey( playerUUIDLSB ) && + getPlayerSlimeJumpCache().get( playerUUIDLSB ).isDisplayMessages() ) { + + DecimalFormat f4Fmt = Prison.get().getDecimalFormat("#,##0.0000"); + + player.sendMessage( "SlimeFun: Exceeded max velocity!! velY:" + f4Fmt.format( velocityY ) ); + } velocityY = 1024.0; } @@ -157,25 +220,31 @@ private double getBoost( ItemStack itemInHand ) // being ran. Material holding = itemInHand.getType(); - if ( holding == Material.DIAMOND_PICKAXE ) { - boost *= 3.0; - } - else if ( holding == Material.matchMaterial( "GOLD_PICKAXE" ) || - holding == Material.IRON_PICKAXE || - holding == Material.STONE_PICKAXE || - holding == Material.matchMaterial( "WOOD_PICKAXE" ) ) { - boost *= 2.85; - } - else if ( holding == Material.DIAMOND_BLOCK ) { - boost *= 1.65; - } - else if ( holding == Material.GOLD_BLOCK ) { - boost *= 1.45; - } - else if ( holding == Material.IRON_BLOCK ) { - boost *= 1.20; + String itemName = holding.name().toLowerCase(); + + if ( getBoosters().containsKey(itemName) ) { + boost *= getBoosters().get( itemName ); } +// if ( holding == Material.DIAMOND_PICKAXE ) { +// boost *= 3.0; +// } +// else if ( holding == Material.matchMaterial( "GOLD_PICKAXE" ) || +// holding == Material.IRON_PICKAXE || +// holding == Material.STONE_PICKAXE || +// holding == Material.matchMaterial( "WOOD_PICKAXE" ) ) { +// boost *= 2.85; +// } +// else if ( holding == Material.DIAMOND_BLOCK ) { +// boost *= 1.65; +// } +// else if ( holding == Material.GOLD_BLOCK ) { +// boost *= 1.45; +// } +// else if ( holding == Material.IRON_BLOCK ) { +// boost *= 1.20; +// } + // switch ( itemInHand.getType() ) // { @@ -246,5 +315,13 @@ public TreeMap getPlayerSlimeJumpCache() { return playerSlimeJumpCache; } + + public TreeMap getBoosters() { + return boosters; + } + + public int getWorldHeight() { + return worldHeight; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index b1c4c6ee4..966b638fc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -1,5 +1,8 @@ package tech.mcprison.prison.spigot.utils; +import java.util.HashSet; +import java.util.List; + import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -9,6 +12,7 @@ import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.mines.data.Mine; @@ -159,6 +163,24 @@ else if ( !mine.hasMiningAccess( sPlayer ) ) { return; } + HashSet allowedMines = new HashSet<>( bomb.getAllowedMines() ); + HashSet preventedMines = new HashSet<>( bomb.getPreventedMines() ); + List globalPreventedMines = (List) Prison.get().getPlatform() + .getConfigStringArray("prison-mines.mine-bombs.prevent-usage-in-mines"); + preventedMines.addAll( globalPreventedMines ); + + // Skip prevent-in-mines check if mine is within the allowedMines list: + if ( !allowedMines.contains( mine.getName().toLowerCase() ) ) { + + if ( preventedMines.contains( mine.getName().toLowerCase() ) ) { + + // Mine bombs are not allowed to be used in this mine so cancel: + event.setCancelled( true ); + return; + } + } + + // getHand() is not available with bukkit 1.8.8 so use the compatibility functions: EquipmentSlot hand = SpigotCompatibility.getInstance().getHand(event); // EquipmentSlot hand = event.getHand(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index b57eb1124..d66e85304 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import org.bukkit.Bukkit; @@ -88,6 +89,8 @@ public static PrisonUtilsMineBombs getInstance() { @Override protected Boolean initialize() { + //validateMineBombs(); + return true; } @@ -457,6 +460,7 @@ public void utilsMineBombsList( CommandSender sender, } } + @Command(identifier = "prison utils bomb give", description = "Gives the player a mine bomb. Can also provide a list of " + @@ -698,6 +702,7 @@ public static ItemStack getItemStackBomb( MineBombData bombData ) { bombs.setLore( lore ); + // SpigotCompatibility.getInstance().setCustomModelData( bombs, bombData.getCustomModelData() ); sItemStack = bombs.getBukkitStack(); } @@ -709,6 +714,11 @@ public static ItemStack getItemStackBomb( MineBombData bombData ) { // nbtItem = new NBTItem( sItemStack, true ); // nbtItem.setString( MineBombs.MINE_BOMBS_NBT_BOMB_KEY, bombData.getName() ); + + // Set the customModelData on the bomb to allow for custom skins: + SpigotCompatibility.getInstance().setCustomModelData( sItemStack, bombData.getCustomModelData() ); + + if ( Output.get().isDebug() ) { Output.get().logInfo( "getItemStackBombs ntb: %s", PrisonNBTUtil.nbtDebugString(sItemStack) ); } @@ -1016,6 +1026,149 @@ else if ( bomb != null ) { } + public boolean validateMineBombsSpigotVersion() { + boolean results = true; + + MineBombs mBombs = MineBombs.getInstance(); + + Map bombs = mBombs.getConfigData().getBombs(); + + Set keys = bombs.keySet(); + for ( String key : keys ) { + MineBombData mbData = bombs.get( key ); + + List deleteSounds = new ArrayList<>(); + for ( MineBombEffectsData sEffect : mbData.getSoundEffects() ) { + + if ( !utilsMineBombsValidate( "sounds", sEffect.getEffectName() ) ) { + results = false; + deleteSounds.add( sEffect ); + + Output.get().logInfo( "MineBomb Validation Error: Invalid sound removed: %s : [%s]", + mbData.getName(), sEffect.toString() ); + } + } + if ( deleteSounds.size() > 0 ) { + mbData.getSoundEffects().removeAll( deleteSounds ); + } + + List deleteVisuals = new ArrayList<>(); + for ( MineBombEffectsData sEffect : mbData.getVisualEffects() ) { + + if ( !utilsMineBombsValidate( "visuals", sEffect.getEffectName() ) ) { + results = false; + deleteVisuals.add( sEffect ); + + Output.get().logInfo( "MineBomb Validation Error: Invalid visual removed: %s : [%s]", + mbData.getName(), sEffect.toStringShort() ); + } + } + if ( deleteVisuals.size() > 0 ) { + mbData.getVisualEffects().removeAll( deleteSounds ); + } + + if ( !utilsMineBombsValidate( "shapes", mbData.getExplosionShape() ) ) { + results = false; + + Output.get().logInfo( "MineBomb Validation Error: Invalid shape changed to 'sphere': %s : [%s]", + mbData.getName(), mbData.getExplosionShape() ); + + mbData.setExplosionShape( ExplosionShape.sphere.name() ); + + } + + + } + + if ( !results ) { + // There was an invalid setting. Save the changed configs: + Output.get().logInfo( "MineBomb Validation: Saving mine bombs due to changes in the configs." ); + + mBombs.saveConfigJson(); + } + + return results; + } + + + public boolean utilsMineBombsValidate( String mbObjectType, + String name + ) { + + boolean results = false; + + if ( mbObjectType == null ) { + Output.get().logInfo( "Prison util MineBomb: utilsMineBombsValidate: Error: objectType is null" ); + } + else if ( name == null ) { + Output.get().logInfo( "Prison util MineBomb: utilsMineBombsValidate: Error: name is null" ); + } + + else if ( !isEnableMineBombs() ) { + + Output.get().logInfo( "Prison's utils command mine bombs is disabled in modules.yml." ); + } + else { + + + if ( mbObjectType.equalsIgnoreCase( "shapes" ) ) { + + List shapes = ExplosionShape.asList(); + for (String shape : shapes) { + if ( shape.equalsIgnoreCase( name ) ) { + results = true; + break; + } + } + + } + + else if ( mbObjectType.equalsIgnoreCase( "sounds" ) ) { + + + for ( XSound p : XSound.values() ) { + if ( p.name().equalsIgnoreCase( name ) ) { + results = true; + break; + } + } + + } + + else if ( mbObjectType.equalsIgnoreCase( "visuals" ) ) { + + // bukkit 1.8.8: +// Effect.values() + + // If running less than MC 1.9.0, ie 1.8.x, then use different code for effects: + boolean is1_8 = new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ; + + if ( is1_8 ) { + for ( Effect p : Effect.values() ) { + if ( p.name().equalsIgnoreCase( name ) ) { + results = true; + break; + } + } + + } + else { + + for ( Particle p : Particle.values() ) { + if ( p.name().equalsIgnoreCase( name ) ) { + results = true; + break; + } + } + } + } + + } + + return results; + } + + // public void placeMineBombItem( MineBombData bomb, SpigotBlock sBlock, SpigotItemStack item ) { // diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardData.java new file mode 100644 index 000000000..e90f54679 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardData.java @@ -0,0 +1,155 @@ +package tech.mcprison.prison.spigot.worldguard; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.platform.Platform; + +public class WorldGuardData { + + private String worldGuardPrefix; + + private boolean enabled; + private String name; + + private String permissionPrefix; + private int priority; + + private boolean denyNonMembers; + private String denyMessage; + + private List flags; + + private int increaseX; + private int increaseZ; + private int increaseY; + + public WorldGuardData( String worldGuardPrefix ) { + super(); + + this.worldGuardPrefix = worldGuardPrefix; + + this.flags = new ArrayList<>(); + + configure(); + } + + private void configure() { + + String wgPrefix = getWorldGuardPrefix(); + + Platform platform = Prison.get().getPlatform(); + + this.enabled = platform.getConfigBooleanFalse( wgPrefix + "enable" ); + + if ( isEnabled() ) { + + this.name = platform.getConfigString( wgPrefix + "name-prefix" ); + + this.permissionPrefix = platform.getConfigString( wgPrefix + "permission-prefix" ); + + this.priority = platform.getConfigInt( wgPrefix + "priority", 10 ); + + this.denyNonMembers = platform.getConfigBooleanFalse( wgPrefix + "deny-non-members" ); + + this.denyMessage = platform.getConfigString( wgPrefix + "deny-message" ); + + List flagKeys = platform.getConfigHashKeys( wgPrefix + "flags" ); + + for (String key : flagKeys) { + boolean includeFlag = platform.getConfigBooleanFalse( wgPrefix + "flags" + "." + key ); + + // Only flags that are enabled are stored: + if ( includeFlag ) { + flags.add( key ); + } + } + + + this.increaseX = platform.getConfigInt( wgPrefix + "increase-x", 0 ); + this.increaseZ = platform.getConfigInt( wgPrefix + "increase-z", 0 ); + this.increaseY = platform.getConfigInt( wgPrefix + "increase-y", 0 ); + + } + + } + + public String getWorldGuardPrefix() { + return worldGuardPrefix; + } + public void setWorldGuardPrefix(String worldGuardPrefix) { + this.worldGuardPrefix = worldGuardPrefix; + } + + public boolean isEnabled() { + return enabled; + } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getPermissionPrefix() { + return permissionPrefix; + } + public void setPermissionPrefix(String permissionPrefix) { + this.permissionPrefix = permissionPrefix; + } + + public int getPriority() { + return priority; + } + public void setPriority(int priority) { + this.priority = priority; + } + + public boolean isDenyNonMembers() { + return denyNonMembers; + } + public void setDenyNonMembers(boolean denyNonMembers) { + this.denyNonMembers = denyNonMembers; + } + + public String getDenyMessage() { + return denyMessage; + } + public void setDenyMessage(String denyMessage) { + this.denyMessage = denyMessage; + } + + public List getFlags() { + return flags; + } + public void setFlags(List flags) { + this.flags = flags; + } + + public int getIncreaseX() { + return increaseX; + } + public void setIncreaseX(int increaseX) { + this.increaseX = increaseX; + } + + public int getIncreaseZ() { + return increaseZ; + } + public void setIncreaseZ(int increaseZ) { + this.increaseZ = increaseZ; + } + + public int getIncreaseY() { + return increaseY; + } + public void setIncreaseY(int increaseY) { + this.increaseY = increaseY; + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardSettings.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardSettings.java new file mode 100644 index 000000000..f9e3b9aa1 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/worldguard/WorldGuardSettings.java @@ -0,0 +1,64 @@ +package tech.mcprison.prison.spigot.worldguard; + +import tech.mcprison.prison.file.JsonFileIO; +import tech.mcprison.prison.output.Output; + +public class WorldGuardSettings { + + public static final String WORLD_GUARD_CONFIG_PREFIX = "prison-mines.world-guard."; + public static final String WORLD_GUARD_CONFIG_REGION_MINE = "region-mine"; + public static final String WORLD_GUARD_CONFIG_REGION_MINE_AREA = "region-mine-area"; + + private String wgPrefixRegionMine; + private String wgPrefixRegionMineArea; + + private WorldGuardData mineRegion; + private WorldGuardData mineAreaRegion; + + public WorldGuardSettings() { + super(); + + wgPrefixRegionMine = WORLD_GUARD_CONFIG_PREFIX + WORLD_GUARD_CONFIG_REGION_MINE + "."; + wgPrefixRegionMineArea = WORLD_GUARD_CONFIG_PREFIX + WORLD_GUARD_CONFIG_REGION_MINE_AREA + "."; + + mineRegion = new WorldGuardData( wgPrefixRegionMine ); + mineAreaRegion = new WorldGuardData( wgPrefixRegionMineArea ); + + String json = new JsonFileIO().toString( this ); + + Output.get().logInfo( "WorldGuardSettings: \n" + json ); + } + + + + + public String getWGPrefixRegionMine() { + return wgPrefixRegionMine; + } + public void setWGPrefixRegionMine(String wgPrefixRegionMine) { + this.wgPrefixRegionMine = wgPrefixRegionMine; + } + + public String getWGPrefixRegionMineArea() { + return wgPrefixRegionMineArea; + } + public void setWGPrefixRegionMineArea(String wgPrefixRegionMineArea) { + this.wgPrefixRegionMineArea = wgPrefixRegionMineArea; + } + + public WorldGuardData getMineRegion() { + return mineRegion; + } + public void setMineRegion(WorldGuardData mineRegion) { + this.mineRegion = mineRegion; + } + + public WorldGuardData getMineAreaRegion() { + return mineAreaRegion; + } + public void setMineAreaRegion(WorldGuardData mineAreaRegion) { + this.mineAreaRegion = mineAreaRegion; + } + + +} diff --git a/prison-spigot/src/main/resources/config.yml b/prison-spigot/src/main/resources/config.yml index 3eaf8a39c..4730ba395 100644 --- a/prison-spigot/src/main/resources/config.yml +++ b/prison-spigot/src/main/resources/config.yml @@ -23,6 +23,42 @@ debug: false + +# Prison support: +# Prison has a lot of built in tools to help us provide you with a higher degree of +# support, and to help make it easier for you. +# One of these features, is the ability to submit details about your server's +# Prison setup so we can review many of the features and settings without having +# to ask tons of questions. It also helps to improve the quality of our help by +# eliminating miscommunication and trying to provide answers off of incorrect +# settings. +# Prison is able to gather various informmation and send it in one or more documents +# and then provide you with one URL to copy and paste to share with us. +# +# submit-service: +# PRIVATEBIN-NET - New default option - This uses an encrypted payload and no one +# can read the posts without the password. All posts are eligable +# to be purged in 1 week. +# URL: privatebin.net - hosted in sweeden +# Options: +# expire: [one_week, one_day, one_hour] +# password: PrisonSupport - default - Do not change this unless you tell +# support team what it is. Odds of someone reading your post is +# limited to only those who may be on our support discord server. +# PASTE-HELPCHAT - This was the default serivce. We no longer recommend using this +# service because: the posts do not expire and are not deletable, +# anyone with the URL can view the contents (improbable the can +# find it due to random URL), and limited to 400k. +# URL: paste.helpch.at - Ran by the folks who publish placeholderAPI. +# Options: none\ +# +prison-support: + submit-service: PRIVATEBIN-NET + expire: 1week + password: PrisonSupport + + + # Upon server startup prison will check to see if a newer version has been released. check-updates: true @@ -83,6 +119,21 @@ prestige: # all functions able to handle new players that have not been added to Prison due to # the degree of complexity of some sections of prison. # +# The 'player-economy-cache-update-delay-ticks' provides the nummber of ticks of a delay +# from when a player is paid money, until the prison updates the econommy. The default +# delay is 3 seconds, or 60 tickks. The purpose of this delayed update is to prevent the +# frequent player payments while speed-mining fromm overwhelming the economy plugin. +# For example, if there are 20 players online, all mining with a highly efficent pickaxe, +# and with autosell enabled, a single player would recieve payments for each block broken, +# of which could quickly exceed 20 to 40 updates per second per player. So with 20 players +# mining concurrently, the econommy plugin would have to be able to handle 400, to 800 +# updates per second, if not more. Some economy plugins cannot handle such loads, and +# can cause the server to lag becaus they are not using asynchronous updates to the storage +# of choice, and they mmay not cache the updates to prevent so many updates. +# If the 3 second delay is too long, and you're wanting something a little quicker, try +# reducing the number of ticks to like 30, 20, or 10. Becareful of going too low. If +# you notice potential server deplays, trying incrasing the delays. You can use +# `/timings` to confirm where the lag is occuring. ranks: startup: @@ -90,6 +141,7 @@ ranks: gui-default-include-rankup-button: true gui-prestiges-include-rankup-button: true gui-others-include-rankup-button: true + player-economy-cache-update-delay-ticks: 60 @@ -120,12 +172,27 @@ integrations: -# NEW: This enables new physics to be applied when jumpping on slime blocks. +# 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. -slime-fun: false +# Boosters are items held in the primary hand of the player, which boosts the +# jump with each bounce. +slime-fun: + enabled: false + display-messages: true + boosters: + diamond_pickkaxe: 3.0 + gold_pickaxe: 2.85 + iron_pickaxe: 2.85 + stone_pickaxe: 2.85 + wood_pickaxe: 2.85 + diamond_block: 1.65 + gold_block: 1.45 + iron_block: 1.20 -# NEW: Prison now has GUIs for most features and actions. For more options + + +# Prison now has GUIs for most features and actions. For more options # please check the GuiConfig.yml. # Access with /gui prison-gui-enabled: true @@ -212,21 +279,6 @@ storageType: "json" -# Hesitancy Delay Penalty - The purpose of the Hesitancy Delay Penalty is to encourage players -# to rankup to the next rank. Once a player exceeds the rankup cost, they start to incurr a -# rankup penalty. The penalty would be based upon the amount over the rankup cost. So if a player -# has 1.1 million, then only 0.1 million will be subject to the penalty and the penalty will be 20%. -# The max value a player can achieve for a rank will be the rankup cost, then the Hesitancy -# Delay Penalty will be subtracted from that amount. -# For example, if the rankup cost would be 1.0 million and a player has 1.1 million, then their -# max "score" they can achieve is 1.0 million, but the 20% penalty on the 0.1 million will be -# subtracted from the "score". So their adjusted score would be: -# 1.0 million - 0.1 million * 0.2 = 1.0 m - 20,000 = 0.8 m -# -top-stats: - rank-players: - hesitancy-delay-penalty: true - # 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 @@ -271,6 +323,39 @@ prison-mines: access-to-prior-mines: true tp-to-spawn-on-mine-resets: true enable-suffocation-in-mines: false + mine-bombs: + prevent-usage-in-mines: + - GoldMine + - SampleMineName + world-guard: + region-mine: + enable: true + name-prefix: prison_mine_ + permission-prefix: "g:prison.mines." + priority: 10 + deny-non-members: true + deny-message: You must rankup to access this mine. + flags: + block-break: true + item-pickup: true + xp-drops: true + item-drop: true + region-mine-area: + enable: true + name-prefix: prison_mine_area_ + increase-x: 15 + increase-z: 15 + increase-y: 9999 + permission-prefix: "g:prison.mines." + priority: 10 + deny-non-members: true + deny-message: You must rankup to access this mine. + flags: + block-break: false + item-pickup: true + xp-drops: true + item-drop: true + @@ -385,6 +470,7 @@ prisonCommandHandler: exclude-worlds: - miniGameWorld - playerPlotWorld + disable-player-placeholders-in-excluded-worlds: false exclude-non-ops: exclude-related-aliases: true commands: @@ -435,3 +521,60 @@ topNPlayers: interval-ticks: 6000 +# Hesitancy Delay Penalty - The purpose of the Hesitancy Delay Penalty is to encourage players +# to rankup to the next rank. Once a player exceeds the rankup cost, they start to incurr a +# rankup penalty. The penalty would be based upon the amount over the rankup cost. So if a player +# has 1.1 million, then only 0.1 million will be subject to the penalty and the penalty will be 20%. +# The max value a player can achieve for a rank will be the rankup cost, then the Hesitancy +# Delay Penalty will be subtracted from that amount. +# For example, if the rankup cost would be 1.0 million and a player has 1.1 million, then their +# max "score" they can achieve is 1.0 million, but the 20% penalty on the 0.1 million will be +# subtracted from the "score". So their adjusted score would be: +# 1.0 million - 0.1 million * 0.2 = 1.0 m - 20,000 = 0.8 m +# +top-stats: + rank-players: + hesitancy-delay-penalty: true + + + + + +# Player-Cache: The player cache stores and tracks a lot of detailed information for +# all players. There are a few settings that can help improve performance, or help +# adjust for your server's requiremments. +# write-delay-sec: Default 60 seconds - There is a player cache task that runs every +# x seconds, based upon this setting. It maintains the cache by +# saving 'dirty' entries, purging entries that have expired (off-line +# player cache entries that have been loaded for longer than the +# time to live value). etc... This task provides the house keeping +# functions, with the most critical aspect being saving changed cached +# entries. This value need to be carefully balanced to help ensure the +# entries are save frequently to protect against loss if the server +# crashes, but also it should be long enough so it does not consume +# too many resources. +# One minute may be a good starting point, but on stable servers, you +# could push it back to about 5 mins, 15 mins, or longer. +# When the server shuts down normally, all dirty entries in the cache +# are tried to be written before the server process is hard-terminated, +# so consideration need to be applied to how many changes can be saved +# before the server gives up and hard-terminates the saves, which could +# result in lost data. +# time-to-live-sec: Default 30 mins. For off line players, if there have been no +# interactions, or usage of their cache entries, they will be purged +# from the cache. This may also apply to online players too, but +# they would have to inactive for this duration. If a player is +# purged from cache, then they will be reloaded when the rejoin the +# server, or there is a need to update, or access their cache entry. +# update-player-stats-sec: Default 30 seconds. Checks to see if all players within the +# player cache who are marked as active are still online. +# This does not update any files and does not interact with +# bukkit/spigot. Very, very minimal impact on server, but +# important to recording player's activity level on the server. +player-cache: + write-delay-sec: 60 + time-to-live-sec: 1800 + update-player-stats-sec: 30 + + + \ No newline at end of file diff --git a/prison-worldguard6/build.gradle b/prison-worldguard6/build.gradle new file mode 100644 index 000000000..224f74b31 --- /dev/null +++ b/prison-worldguard6/build.gradle @@ -0,0 +1,120 @@ +/* + * Prison is a Minecraft plugin for the prison game mode. + * Copyright (C) 2017 The Prison Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +group 'tech.mcprison' + +apply plugin: 'java' + +compileJava.options.encoding = 'UTF-8' +compileTestJava.options.encoding = "UTF-8" + +//sourceCompatibility = 1.8 + + +// https://www.spigotmc.org/wiki/spigot-gradle/ + + +repositories { + mavenCentral() + + + maven { + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + + // As of Gradle 5.1, you can limit this to only those + // dependencies you expect from it + content { + includeGroup 'org.bukkit' + includeGroup 'org.spigotmc' + } + } + /* + As Spigot-API depends on the BungeeCord ChatComponent-API, + we need to add the Sonatype OSS repository, as Gradle, + in comparison to maven, doesn't want to understand the ~/.m2 + directory unless added using mavenLocal(). Maven usually just gets + it from there, as most people have run the BuildTools at least once. + This is therefore not needed if you're using the full Spigot/CraftBukkit, + or if you're using the Bukkit API. + */ + maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + maven { url = 'https://oss.sonatype.org/content/repositories/central' } + + // mavenLocal() // This is needed for CraftBukkit and Spigot. + maven { + url "https://mvnrepository.com/artifact" + } + + maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } + + maven { url = "https://maven.enginehub.org/repo/" } +} + + + +dependencies { + implementation project(':prison-core') +// implementation project(':prison-mines') +// implementation project(':prison-ranks') +// implementation project(':prison-sellall') + + + compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + + + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-core + // Artifact located at repo: https://maven.enginehub.org/repo/ + implementation 'com.sk89q.worldedit:worldedit-core:6.0.1' + //implementation 'com.sk89q.worldedit:worldedit-core:7.2.15' + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-bukkit + // Artifact located at repo: https://maven.enginehub.org/repo/ + compileOnly 'com.sk89q.worldedit:worldedit-bukkit:6.1.5' + //compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.15' + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-legacy + // NOTE: although the following does exist, its unable to be pulled in so instead + // the jar is included. + //compileOnly 'com.sk89q.worldguard:worldguard-legacy:6.1.2' + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-core + //compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-bukkit + //compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard.worldguard-libs/core + //implementation 'com.sk89q.worldguard.worldguard-libs:core:7.0.8' + + + + + compileOnly fileTree(dir: 'lib', include: ['*.jar'] ); + + + + + testImplementation group: 'junit', name: 'junit', version: '4.12' + +} + + + diff --git a/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldEdit6.java b/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldEdit6.java new file mode 100644 index 000000000..d5f1345d4 --- /dev/null +++ b/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldEdit6.java @@ -0,0 +1,28 @@ +package tech.mcprison.worldguard6.worldguard; + +import tech.mcprison.prison.worldguard.PrisonWorldEdit; + +public class PrisonWorldEdit6 + extends PrisonWorldEdit +{ + + public PrisonWorldEdit6() { + super(); + + } + + public void getWorldEditActor( org.bukkit.entity.Player bukkitPlayer ) { + +// Player results = BukkitAdapter.; + +// Bukkit + + + +// com.sk89q.worldedit.bukkit.BukkitPlayer; +// BukkitAdapter.; + +// return results; + } + +} diff --git a/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldGuard6.java b/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldGuard6.java new file mode 100644 index 000000000..e747056e3 --- /dev/null +++ b/prison-worldguard6/src/main/java/tech/mcprison/worldguard6/worldguard/PrisonWorldGuard6.java @@ -0,0 +1,14 @@ +package tech.mcprison.worldguard6.worldguard; + +import tech.mcprison.prison.worldguard.PrisonWorldGuard; + +public class PrisonWorldGuard6 + extends PrisonWorldGuard +{ + + public PrisonWorldGuard6() { + super(); + + } + +} diff --git a/prison-worldguard7/build.gradle b/prison-worldguard7/build.gradle new file mode 100644 index 000000000..c8b574c24 --- /dev/null +++ b/prison-worldguard7/build.gradle @@ -0,0 +1,129 @@ +/* + * Prison is a Minecraft plugin for the prison game mode. + * Copyright (C) 2017 The Prison Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +group 'tech.mcprison' + +apply plugin: 'java' + +compileJava.options.encoding = 'UTF-8' +compileTestJava.options.encoding = "UTF-8" + +//sourceCompatibility = 1.8 + + +// https://www.spigotmc.org/wiki/spigot-gradle/ + + +repositories { + mavenCentral() + + + maven { + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + + // As of Gradle 5.1, you can limit this to only those + // dependencies you expect from it + content { + includeGroup 'org.bukkit' + includeGroup 'org.spigotmc' + } + } + /* + As Spigot-API depends on the BungeeCord ChatComponent-API, + we need to add the Sonatype OSS repository, as Gradle, + in comparison to maven, doesn't want to understand the ~/.m2 + directory unless added using mavenLocal(). Maven usually just gets + it from there, as most people have run the BuildTools at least once. + This is therefore not needed if you're using the full Spigot/CraftBukkit, + or if you're using the Bukkit API. + */ + maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + maven { url = 'https://oss.sonatype.org/content/repositories/central' } + + // mavenLocal() // This is needed for CraftBukkit and Spigot. + maven { + url "https://mvnrepository.com/artifact" + } + + maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } + + + maven { url = "https://maven.enginehub.org/repo/" } +} + + + +dependencies { + implementation project(':prison-core') +// implementation project(':prison-mines') +// implementation project(':prison-ranks') +// implementation project(':prison-sellall') + + + compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + + + // API Docs: https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-core/7.2.0/ + + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-core + // Artifact located at repo: https://maven.enginehub.org/repo/ + //implementation 'com.sk89q.worldedit:worldedit-core:6.0.1' + implementation 'com.sk89q.worldedit:worldedit-core:7.2.15' + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-bukkit + // Artifact located at repo: https://maven.enginehub.org/repo/ + //compileOnly 'com.sk89q.worldedit:worldedit-bukkit:6.1.5' + compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.15' + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-legacy + // NOTE: although the following does exist, its unable to be pulled in so instead + // the jar is included. + //compileOnly 'com.sk89q.worldguard:worldguard-legacy:6.1.2' + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-core + // Artifact located at repo: https://maven.enginehub.org/repo/ + // WARNING: v7.0.4 is the last release that ia java 1.8 compatible + compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.4' + //compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.5' + // requires java 16: compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.6' + // requires java 16: compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.7' + // requires java 17: compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-bukkit + // Artifact located at repo: https://maven.enginehub.org/repo/ + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4' + //compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard.worldguard-libs/core + implementation 'com.sk89q.worldguard.worldguard-libs:core:7.0.4' + //implementation 'com.sk89q.worldguard.worldguard-libs:core:7.0.8' + + + + + + + testImplementation group: 'junit', name: 'junit', version: '4.12' + +} + + + diff --git a/prison-worldguard7/build.gradle.txt b/prison-worldguard7/build.gradle.txt new file mode 100644 index 000000000..4997d8bb5 --- /dev/null +++ b/prison-worldguard7/build.gradle.txt @@ -0,0 +1,116 @@ +/* + * Prison is a Minecraft plugin for the prison game mode. + * Copyright (C) 2017 The Prison Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +group 'tech.mcprison' + +apply plugin: 'java' + +compileJava.options.encoding = 'UTF-8' +compileTestJava.options.encoding = "UTF-8" + +//sourceCompatibility = 1.8 + +repositories +{ + mavenCentral() +. + maven { + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + + // As of Gradle 5.1, you can limit this to only those + // dependencies you expect from it + content { + includeGroup 'org.bukkit' + includeGroup 'org.spigotmc' + } + } + /* + As Spigot-API depends on the BungeeCord ChatComponent-API, + we need to add the Sonatype OSS repository, as Gradle, + in comparison to maven, doesn't want to understand the ~/.m2 + directory unless added using mavenLocal(). Maven usually just gets + it from there, as most people have run the BuildTools at least once. + This is therefore not needed if you're using the full Spigot/CraftBukkit, + or if you're using the Bukkit API. + */ + maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + maven { url = 'https://oss.sonatype.org/content/repositories/central' } + + // mavenLocal() // This is needed for CraftBukkit and Spigot. +// maven { +// url "https://mvnrepository.com/artifact" +// } + + //maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } + + //maven { url = "https://maven.enginehub.org/repo/" } + +} + + + +dependencies { + implementation project(':prison-core') +// implementation project(':prison-mines') +// implementation project(':prison-ranks') +// implementation project(':prison-sellall') + + + compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + + + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-core + implementation 'com.sk89q.worldedit:worldedit-core:7.2.15' + + // https://mvnrepository.com/artifact/com.sk89q.worldedit/worldedit-bukkit + compileOnly 'com.sk89q.worldedit:worldedit-bukkit:7.2.15' + + + + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-core + compileOnly 'com.sk89q.worldguard:worldguard-core:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-bukkit + compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.8' + + // https://mvnrepository.com/artifact/com.sk89q.worldguard.worldguard-libs/core + implementation 'com.sk89q.worldguard.worldguard-libs:core:7.0.8' + + + + + // 1.9.4-R0.1-SNAPSHOT has been the version used for a long time: +// compileOnly 'org.spigotmc:spigot-api:1.9.4-R0.1-SNAPSHOT' + // 1.12.2-R0.1-SNAPSHOT works well: +// compileOnly 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT' + // 1.13.2 fails since deprecated functions have been removed. + //compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + + + + + + + testImplementation group: 'junit', name: 'junit', version: '4.12' + +} + + + diff --git a/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldEdit7.java b/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldEdit7.java new file mode 100644 index 000000000..d2055aab4 --- /dev/null +++ b/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldEdit7.java @@ -0,0 +1,28 @@ +package tech.mcprison.worldguard7.worldguard; + +import tech.mcprison.prison.worldguard.PrisonWorldEdit; + +public class PrisonWorldEdit7 + extends PrisonWorldEdit +{ + + public PrisonWorldEdit7() { + super(); + + } + +// public void getWorldEditActor( org.bukkit.entity.Player bukkitPlayer ) { +// +//// Player results = BukkitAdapter.; +// +//// Bukkit +// +// +// +//// com.sk89q.worldedit.bukkit.BukkitPlayer; +//// BukkitAdapter.; +// +//// return results; +// } + +} diff --git a/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldGuard7.java b/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldGuard7.java new file mode 100644 index 000000000..0a6ab89a2 --- /dev/null +++ b/prison-worldguard7/src/main/java/tech/mcprison/worldguard7/worldguard/PrisonWorldGuard7.java @@ -0,0 +1,14 @@ +package tech.mcprison.worldguard7.worldguard; + +import tech.mcprison.prison.worldguard.PrisonWorldGuard; + +public class PrisonWorldGuard7 + extends PrisonWorldGuard +{ + + public PrisonWorldGuard7() { + super(); + + } + +} diff --git a/settings.gradle b/settings.gradle index a840f34b9..7b7f2ca03 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,3 +24,11 @@ include 'prison-spigot' include 'prison-mines' include 'prison-ranks' include 'prison-sellall' + +include 'prison-misc' + +include 'prison-worldguard6' +include 'prison-worldguard7' +/* +include 'prison-worldguard8' +*/